|
56428
|
1967
|
27
|
2026-05-19T08:06:09.958178+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177969958_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6870583155641010293
|
-8132287983061324858
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
PhpStormViewNavigateCodeLaravelRefactorTOOISWindowFV faVsco.jsv?9 JY-20676-delete-report-related-objectsProiect vC) AutomatedReport.onp© AskAnythingPromptServiceTest.php© ActivityAskAnythinglest.phpe) -xooricontro||erRateLimit est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpC)FakeProphetClient.oho© AskAnythingPromptService.ph© BaseService.phpMidd lewareM RequestsSoftPhoneManager.phpC) RoleAttr.png© ScimProvisioning.php() ListenerRoleCannotHaveAdminOrMa() RoleAttrTest.phpInteractionsInvitationsalobs" ListenerRoleCannotHaveAdminOrManagerPermissionRule.php© Activity/Close/Service.php©) Activity/RinqCentral/Service.phpListeners© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpD McpModelsD NotificationsD OrganizationSettingsD PlaylistsD Policies( RepositoriesC Rules0 SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search> C ServiceProvidersfinal class SavedSearchCRUDFeatureTest extends TestCase194 D >255256257 D >314public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}#[\PHPUnit\Framework\Attributes\Test]public function userCanDeleteASavedSearch: void{...}Local ChandesConsole XLooXv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnything© AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos© AskAnythingPromptService.php app/Component/AskAnything@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2T.O©® Side-by-side viewerCurrent version raw sal querv.sallDo not ignoreHighlight words ?SELECT activities. *C) Constants.ono apo/Comoonent/SClM© CoreUser.php app/DTO/SCIM/AAD/ResponseC) CoreUserRequest.ono aoo/DTO/SCIMIAAD/Requesi© JiminnyDebugCommand.php app/Console/CommandsC ListenerRoleCannotHaveAdminOrManagerPermissionRule.php app/Rules@* ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Unit/FFROM activitiesINNER JOIN activity_processing_states AS aps ON aps.activity_id = activities.idINNER JOIN users ON users.id = activities.user_idWHERE activities.is_internal = 0AND users.status = 1AND activities.type NOT IN ('email_inbound', 'email_outbound',AND aps.state = 'send_processing_notificationsAND aps.status IN ('finished', 'failed')AND aps.created_at BETWEEN ? AND ?AND aps.deleted_at IS NULL-- Optional team filter (add when teamId is provided):-- AND users.team id = ?php logging.php config© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Usec) RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/Use@ ScimProvisioning.php app/Component/SCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt appT raw sal querv.sal apn© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotMJ WEBHOOK FILTERING IMPLEMENTATION.md annThe Hunspell plugin has been deprecated. If you're not writing in Hungarian, you can safely uninstall Hunspell without affecting the dicries for other languages. (today 10:00)"suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:09U AskJiminnyReportActivityServiceTest v+0 ..= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]& console [EU]A console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~29 6t34 6t >A3416 ^ v45 6t- 119- 131135136 >public function construct(UserRepository SuserRepository){...}public function shouldApplyQueries: bool{...}public function getQueries: FilterDefinitionQueryCollection{...}ouolic function toArravo: arrav...?1 usaadprivate function getOptions: arrayt...public function getValue: arrayt...lusageprivate function getDefaultValue: arrayt...public function getValidationRules(?string $prefix = null): array{...}CascadeAsk Jiminny Report Mmocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['ask_anything_prompt_id' = null, 'status' = falsel ).Per your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.8 files 400-7 )Ask anvthina (4D1+ <> Code Claude Opus 4.7 Medium* Reject allAccept allW Windsurf Teams 314:1 UTF-8 P 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56429
|
1967
|
28
|
2026-05-19T08:06:11.621779+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177971621_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
56428
|
NULL
|
NULL
|
NULL
|
|
56430
|
1966
|
23
|
2026-05-19T08:06:11.007655+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177971007_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7900466997463401669
|
-5826444973847630902
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:10QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A687Message #the_people_of_jiminny+...
|
56427
|
NULL
|
NULL
|
NULL
|
|
56431
|
1966
|
24
|
2026-05-19T08:06:13.015829+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973015_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56432
|
1967
|
29
|
2026-05-19T08:06:13.018092+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973018_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56433
|
1967
|
30
|
2026-05-19T08:06:13.768774+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973768_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"}]...
|
7416589213088100201
|
-8996616126076344540
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project...
|
56432
|
NULL
|
NULL
|
NULL
|
|
56434
|
1967
|
31
|
2026-05-19T08:06:14.764810+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177974764_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56435
|
1966
|
25
|
2026-05-19T08:06:16.356352+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177976356_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6966022010367698874
|
-564708849257816637
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:16QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A687Message #the_people_of_jiminny+...
|
56431
|
NULL
|
NULL
|
NULL
|
|
56436
|
1967
|
32
|
2026-05-19T08:06:16.376487+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177976376_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5235617535283860069
|
-8132292381107834938
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
iilPhostormVIewINavicareCodeLaravelKeractorTOOISFV faVsco.js°9 JY-20676-delete-report-related-objectsProiectC) AutomatedReport.onp© AskAnythingPromptServiceTest.php- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpe) -xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv© BaseService.php> _ Midd ewareC SoftPhoneManager.phpC) RoleAttr.png© ScimProvisioning.phpRequests() ListenerRoleCannotHaveAdminOrMa() RoleAttrTest.phpInteractionsInvitationsListenerRoleCannotHaveAdminOrManagerPermissionRule.phpC) Activity/Close/Service.php© Activity/RingCentral/Service.phpIHlobsListeners© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpD McpN Modelsifinal class SavedSearchCRUDFeatureTest extends TestCase194 D >public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}M NotificationsD OrganizationSettingsD PlaylistsD Policies257 D >#Phrun1c rramework Accribuces lescpublic function userCanDeleteASavedSearch: void{...}314_ kepositonesC RulesC SavedSearchesSavedSearchCRUDFeatureTest.php› C Search›_ serviceProvidersConsole XLoo Xv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingc) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros© AskAnvthinaPromptService.php app/Component/AskAnvthina@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/APIV2→© Side-by-side viewerDo not ignoreHighlight wordsx 158 5604af40 app/Compuse Jiminny Models Role:use liminnv Model c Team:use Jiminny Models\User;use liminnv Senvices IlsenSenvice.use Sentry:C) Constants.ono aoo/CC) Coreuser.ono aoo/DIO/SCIMIAAD/Resoonseclass ScimProvisioningC) CoreUserRequest.ono ano/DTO/SCIMIAAD/Request© JiminnyDebugCommand.php app/Console/Commands@ ListenerRoleCannotHaveAdminOrManagerPermissionRule.pho apn/RulesQ ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Urpublic function _construct(private readonly Dispatcher SeventDispatcherphp loadina.nho confialorivace readonly userservice suserserviceprivate readonly RoleChangeLogger SroleChangeLoggerC RoleAttr.nho aoo/Comnonent/SCIM/Mutators/Attributes/Use') RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/UseriC CcimDrovicionina nhn ann/Camnonent/CCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt apdTraw saL querv.sal app© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERINGIMPLEMENTATION.md aprpublic function validateUserIdInput($id, Team Steam): boolT'email' => Sdto->qetEmailPrimaryWorkO],SuserUodateDatalif (! SnewUser->roles()->exists()) {Snewliser->addRole User: ROLE ANALYSTO:/** @var Role Srole */Snole = Role• •quervo->whenedr'namel => Isen• •ROI F ANAI VSTD->finctinSailo•Tihe Hunsnelinluain has been denrecated lfivouire not writinalin ungarian vou can safelvmninstalllHunsnellwithout affectina the diationaries for athez lanauades /today 10:00= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~pubLic tunccion conscruct userkeposicory suserkeposicorw?...29 6tpublic function shouldApplyQueries: bool{...}34 6t >public function getQueries: FilterDefinitionQueryCollection{...}A3416 ^ v45 6tpubLic function toArray): arrayl...л1 usaadprivate function getOptions: arrayt...=119=130public function getValue: arrayt...=131lusageprivate function getDefaultValue: arrayt...Ask anvthina (4D1136 >public function getValidationRules(?string $prefix = null): array{...}4 @s Codo Chudo Onuc 17 ModiumCurrent versionuse Jiminny Models Role;use liminnv Model c Teamuse Jiminny Models\User;luse liminnv Senvices IlcenSenvico•use Jiminny\Contracts\Acl \RoleRepositoryInterface:use Illuminate\Support\Facades|VaLidaton.use Jiminny Rules\DependentRolesRule:use Jiminny Rules\ListenerRoleCannotHaveAdmin0rManagerPermissionRule:use Jiminny Rules \ListenerRoleRequiresListenerFeatureRuleuse Jiminny Actions UpdateUserRolesAction:use Jiminny DTO\Roles UserRolesSyncDT0:use Sentry:class Sc1mProv1s10n1nqlpublic function -_constructorivate readonly Daspatcher seventiisoatcher.private readonly UserService $userService,orivate readonly RolechangeLogger SroleChangeLogger..orivate readonly RoleRepositoryInterface $roleRepository,orivate readoniv UodatelserRolesAction SundatelserRolesAction.nublic function validatellsenTdinnut(Sid. Team Steam• hooll• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:16AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt id is nult. Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alli•01.4 difterencesWN Windsurf Toams 214-1UTF.8ih 4 spaces...
|
56434
|
NULL
|
NULL
|
NULL
|
|
56437
|
1967
|
33
|
2026-05-19T08:06:18.458477+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177978458_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56438
|
1966
|
26
|
2026-05-19T08:06:21.384837+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177981384_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4508586470331655935
|
-8996598804337712604
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56439
|
1967
|
34
|
2026-05-19T08:06:21.347599+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177981347_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
56437
|
NULL
|
NULL
|
NULL
|
|
56444
|
1966
|
28
|
2026-05-19T08:06:35.786634+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177995786_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% <7Tue 19 May 11:06:35QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4637Message #the_people_of_jiminny+...
|
NULL
|
-301870021424380514
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% <7Tue 19 May 11:06:35QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4637Message #the_people_of_jiminny+...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56445
|
1967
|
38
|
2026-05-19T08:06:36.174245+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177996174_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.19952115,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.19952115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.19792499,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7900466997463401669
|
-5826444973847630902
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
PhostormViewINavicareCodeKeractorTOOISWindowFV faVsco.js°9 JY-20676-delete-report-related-objectsProiectC) AutomatedReport.onp© AskAnythingPromptServiceTest.php- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php Xe) -xooricontro||erRateLimit est.onoAsKAnywingPromptuto.pnpC) FakeProphetClient.ohv© BaseService.php> _ Midd ewareC SoftPhoneManager.phpgscimProvisioning.phpRequestsAcuivily/close/service.ohol Interactionsa Invitations(C) TextMessaqingService.phgIHlobsfinal class SavedSearchCRUDFeatureTest extends TestcaseщЛ2A16 A VIn ListenersD McpN Modelsi194 D >#[\PHPUnit\Framework\Attributes\Test]public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}M Notificationsm oraanizationsettingsD PlaylistsD Policies( RepositoriesC RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search257 D >#[\PHPUnit\Framework\Attributes\Test]public function userCanDeleteASavedSearch: void{...}_ serviceProvidersLocal ChandesConsole XLooXHighlight words x 15 ?Scim orovisionina with rioles 8 files. Mom.&Base version app/Component/SCIM/Constants.php> CrmOwnerResolver 2 files. A minute aad> JY-20891 SMS Text relav EU 3 files. 15.05.26. 14:05.> JD & SendRenort.Job 2 files. 13.05.26. 12•38> reorder calls 1 file. 11.05.26. 10:09Move non naainator coarch callc to client-scoarch 1 file 11.05 26 . 10-07• Almast readv one call to he tected & filec 8 05 26 14-54> hubsnot rate limit temn checkout 17 filec 8 05 26 11-49public const META_ID = 'id':public const META_PHONE_NUMBERS = 'phoneNumbers' :public const META TITLE = 'title':public const META PATH = 'path':public const META ENTERPRISE SCHEMA = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User':> caved coarch delete 1 file 27 04 26 14-59public const META DEPARTMENT = "department'*public const META_META = 'meta';› expiration message 6 files, 27.04.26, 9:23• 1Ip dev loac 1 file 2404 26 12.021› tem test 1 file, 24.04.26, 10:36)ucor trancfarmor 2 filoc 2204 06 15012public const USER PATCH ATTR PRIMARY EMAIL = 'emailsitvpe ea "work"].value'•ouounc const USER PATCHATIR SECONDARY EMAIL ='emalis tvoe ed "home",value',> email ready 9 files, 23.04.26, 15:31> Email on not sent 5 files. 21.04.26, 19:38> Planhat track interest event 2 files. 21.04.26. 13:56> UP tracking controller 1 file. 20.04.26, 9:22> Don't send if no s3 path (fix update to failed) 1 file. 17.04.26. 12:56> FEATURE CHANGES 3 files. 6.04.26. 13:40oublic const USER PATCH ATTR PHONE NUMBER = "ohoneNumbers tvoe ea "work" value':nublic constUSER_PATCH_ATTR_PHONE_NUMBER_MOBILE = 'phoneNumbers[type eq "mobile"].value';oublic const USER SUPPORTED PATCH ATTRIBUTES MUTATORS =self::USER_PATCH_ATTR_TITLE => Mutators\Attributes\User\TitleAttr::class,Se+.•USER PATCHATTR ACTTVE= Mutatons Attrihutes Uisen ActiveAttn:.cllass.web,oho tix router 1 tile, 1.04.26, 9:23|> SF Tvpe error fix 2 files. 31.03.26. 12:26> next automated report task 1 file. 31.03. 26. 10:55)• who knows 2 files. 24.03, 26. 14:45> temo fix 32 files. 24.03.26. 10:51lself:-USER PATCH ATTR PRIMARY EMATI => Mutatons Attrihutes Isen PnimanvEmailAttn:classlself::USER_PATCH_ATTR_SECONDARY_EMAIL => Mutators\Attributes\User\SecondaryEmailAttr::class,solf.-ISER PATCH ATTR PHONE NUMRER => Mutatons Attnihutes Ilsen PhoneNumhenPnimanvAttn.•classlself::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE => Mutators\Attributes\User\PhoneNumberSecondaryAttr::class.env local not sure why it was chanded 1 file. 24.03.26. 10:04> Al Renorts 21 files. 19.03.26. 18:07> ORJECT WERHOOK PROCESSING 5 files. 5.03.26. 15:22public const FILTER_OPERATOR_EQ = 'eq';• OR.ISCT RATCH CYNC 12 fllec 5 02 26 15:21The Hunsnell nluain hac heon denrecated. If vou're not writing in Hungarian vou can cafolv uninctall HuncnelliJanquades (todav 10-00)• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:35AskJiminnyReportActivityServiceTest v= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyCascadeA console [STAGING]© CoachingFeedbackCoachUserln.php XAsk Jiminny Report M+0 ..final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini mmocd → null, "status → Talsel3. loggle validation29 6tpublic function shouldApplyQueries: bool{...}rtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. Tests34 6tpublic function getQueries: FilterDefinitionQueryCollection{...}45 6touolic function toArravo: arrav...?AskAnythingPromptServiceTest.php — Updated two existing update() mock expectations to match the new payload (['ask_anything_prompt_id' = null, 'status' = falsel ).Per your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.1 usage=118private function getOptions: arrayt...public function getValue: arrayt...usage8 files 400-7 )Reiect allAccent alliprivate function getDefaultValue: arrayt...135136 >Ask anvthina (*4D1public function getValidationRules(?string $prefix = null): array{...}+ <> Code Claude Opus 4.7 Medium•01.3 ditterencesa Shelved versionpublic const META_ID = 'id';public const META_PHONE_NUMBERS = 'phoneNumbers':public const META TITLE = 'title':Ist META ROLES = 'roles' :public const META PATH = 'path':public const META ENTERPRISE SCHEMA = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User':public const META DEPARTMENT = 'department':public const META META = "meta'"ouounc const USER PATCh ATIR PRIMARY EMAILE'emaris tvoe ed "work"', value',public const USER PATCH ATTR SECONDARY EMAIL = 'emailsityne eo "home"].value'•nublic const USER PATCH ATTR PHONE NUMBER = 'ohoneNumbers tvoe ea "work"] value':public const USER_PATCH_ATTR_PHONE_NUMBER_MOBILE = 'phoneNumbers[type eq "mobile"].value':publicUSER PATCH ATTR ROLES = 'rolesnuhiie cons+ USER SUPPORTED PATCH ATTRIRUTES MUTATORS =self::USER_PATCH_ATTR_TITLE => Mutators|Attributes\User\TitleAttr: :class,self:-ISER PATCH ATTR ACTTVE => Mutatons Attrihutesllsen ActiveAttn.-class.solf.-ISER PATCH ATTR PRTMARV EMATI => Mutatons Attnihutes Iisen PnimanvEmailAttn.class.self::USER_PATCH_ATTR_SECONDARY_EMAIL => Mutators\Attributes\User\SecondaryEmailAttr::class,solf.-lSER pATcH ATTR PHONE NUMRER => Mutatonc Attrihutes Ilsen PhoneNumhenPnimanvAttn.•class.self::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE => Mutators\Attributes\User\PhoneNumberSecondaryAttr::class,self::USER_PATCH_ATTR_ROLES => Mutators\Attributes\User\RoleAttr::class,WN Windsurf Teams214-1UTC.81io 4 spaces...
|
56443
|
NULL
|
NULL
|
NULL
|
|
56446
|
1966
|
29
|
2026-05-19T08:06:39.794123+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177999794_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56444
|
NULL
|
NULL
|
NULL
|
|
56447
|
1967
|
39
|
2026-05-19T08:06:39.726314+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177999726_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.19952115,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.19952115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.19792499,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.19792499,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53093
|
1861
|
6
|
2026-05-18T11:36:21.120462+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779104181120_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4235983745889776938
|
-8204421443435123770
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
PhostormVIewINavicarecodeLaravelKeractorFV faVsco.js°9 master kProiectC ActivityController.ong>@ Builders© CoreUserRequest.phpScimProvisioning.php x © TextMessagingService.phpv D Mutatorsv D Attributesuse stmanny urulouenlaau request loecoroupbyquery>D Groupuse Jemanny uiu suln aau recuesc becuserbyuueryv D Useruse Jemanny Uiu suLn aau request racchoroupuse Jiminny evencs users usercreacedC) ACuiveAttr.ono© FirstNameAttr.phpuse Jiminny Models broup(C) LastNameAttr.phpuse Jiminny Models JobTitle:© PhoneNumberPrimaryAttr.phpJininny Models kolec) PhoneNumberSecondarvAttr.onuse Jiminny Models leam© PrimarvEmailAttr.phpJiminny Models userC) RoleAttr.ohpJiminny Contracts Acl Rolerepos1torvinterface:c) SecondarvemailAttr.onoC) TiitleAttronouse Illuminate Support\Facades\ Validator:(C) UsernameAttr.ohoJaminny Rules DependentRolesrule'C GrouoMutator.ohouse Jiminny Rules ListenerRoleRequtrestastenerFeaturerule:C UserMutator.phpuse Jaminny Actlons UodatelserRoLesaction:© GroupPatchOperation.php© UserPatchOperation.phpuse Jiminny DTO Roles \UserRolesSyncDTO;use Sentry:c) Conctants nhn© Sciminterface.phpclass ScimProvisioningc) ScimProvisioning.gnpM Seederpublic functionconstructD Sentryprivate readonly Dispatcher SeventDispatcher,nnivate neadoniv IlsenSenvice SucenSenvice.1M SerializenD Settingsprivate readonly RoleChangeLogger SroleChangeLoggerSidekick0 Teaminsights0 TimeMemoryMapperAccept File 2+public function validateusertameceptfie aream Rteat le bo0d+ 2of A filoc →Local Chanaes• Chances 7 tlles, uodatino.= env.local apo@cb4ebf0c config/logging.php• Constants.php app/Component/SCIM(C) CoreUserRequest.oho aoo/DTO/SCIMIAAD/Reauest'driver' =>lennonloa!@JiminnvDebuaCommand.oho app/Console/Comma'level' => env('LOG _LEVEL', 'info'),php loadina,oho confid@) SoftPhoneManager.phn ann/Comnonent/Twilio/Conference/ConferenceMa'path' => storage_path('logs/Laravel.log').C) TeytMescacinaService.ohn ann/Services/Telenhonv• Unversioned Files 10 filesi= env nikilocal annl= .env.other appC) CanAccoccAiRenortsTect nhn tests/Unit/Policiod@ CrostoMockAck liminnvDanortPacultCommand.nhnann/Concole/Commandc/Do favicon ico nublicFide tut anrT raw sal query.sql app© RoleAttr.php app/Component/SCIM/Mutators/Attributes/User© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK_FILTERING_IMPLEMENTATION.md appr' hac heon rectored Il Pollback II Confiaure (16 minutec aao))Accept Reñect• suppont Dally • In 24 m100% 2• Mon 18 May 14:36:20AskJiminnyReportActivityServiceTest vFixing Redis Rate LimSalestorce Token FalliSClM Role Manager+0 ..= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]A console [STAGING] X556562568Tx: Auto vselect * from teams:SELECT r.* FROM automated_reports rjoin teams t on r.team.id = t.idWHERE r.freguency = 'daily'and r.status = 1AND t.status = 'active'AND (r.expires_at >= now OR r.expires_at IS NULL);select * from automated_report_results where report id IN (18, 33):select * from users where team_id = 1 and id = 1047:SELECT * FROM social_accounts WHERE sociable_id = 1047;select * from activity searches where id = 10932select * trom activity search tilters where activity search 10 = 109521select * tromorder by 10 descautomated_report_results order by id desc;automated reports where 10 IN (55select * from automated report results where id IN (81):select * trom users where 1d IN 00055,15787,11985071select * trom users where qroup 10 In (5/0):SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROMIautomated_report_results WHERE uuid_to_bin( 582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;select * from teams:Current vercion& console [PROD]# console leuyCascadeImplement Trial OwneGo jiminny_jupiter019 A19 V17 ^ V•Constants.phpThought for 1s>•Constants.phpThought for 1s›• Constants.phpRoleAttr.php|Thouahtso10 lasks done• Create RoleAttr mutator for SCIM© Update ScimProvisioning to handle roles during user creationThoucht for 2c s• ScimProvisioning.phpmllesetAsk anvthina (%4L)+ @code SWE-1.6new +170100 tokensReject allAccept allO901ditterence'driver' => 'errorlog','level' => env('LOG_LEVEL', 'info'),'path' => storage_path('logs/Laravel.log').'custom channel' => ['driver' => 'single','path' => storage_path('loqs/custom.10g')'level' => env('LOG LEVEL', 'info').W Windsurf Toams 1'1UTF.8io 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53094
|
1860
|
5
|
2026-05-18T11:36:27.468184+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779104187468_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
if (! $newUser->roles()->exists()) {
$newUser->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $newUser,
role: $role,
type: $newUser->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n if (! $newUser->roles()->exists()) {\n $newUser->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $newUser,\n role: $role,\n type: $newUser->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n if (! $newUser->roles()->exists()) {\n $newUser->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $newUser,\n role: $role,\n type: $newUser->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5292261031256091635
|
5517158551046434195
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
if (! $newUser->roles()->exists()) {
$newUser->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $newUser,
role: $role,
type: $newUser->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53096
|
1860
|
6
|
2026-05-18T11:36:57.729051+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779104217729_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2220240040950549119
|
5527256463689486230
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error...
|
53094
|
NULL
|
NULL
|
NULL
|
|
53099
|
1861
|
9
|
2026-05-18T11:37:38.906270+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779104258906_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormVIewINavicarecodeLaravelKeractorFV faVsco. PhostormVIewINavicarecodeLaravelKeractorFV faVsco.js°9 master kProiect© SoftPhoneManager.php© PhoneNumberSecondaryAttr.phC CoreUserRequest.phpscimProvistoning.onpx© PrimaryEmailAttr.php© TextMessagingService.php© RoleAttr.php© SecondaryEmailAttr.phpuse Jiminny DTO\SCIM\AAD \Request \GetUserByQuery:© TitleAttr.phpc usernameAuur.onouse Jiminny DTO\SCIM\AAD \Request \PatchGroup;use Jiminny \Events\Users\UserCreated;© GroupMutator.phpuse Jiminny Models \Group;C UserMutator.phpuse Jiminny Models\JobTitle;c) GroupPatchOperation.phpuse Jiminny Models kole.C) UserPatchOperation.phpuse Jiminny Modets rean,c) constants.ohpuse Jiminny Modeusluser@ Sciminterface.phpuse Jiminny services userservice.c) ScimProvisionina.onouse szninny concracts Act kolekepostcoryencerraceSeedenuse Lulumanare supporc racades valzdacor.Sentryuse Jiminny Rules DependentRolesRule:17 Serializenuse Jiminny kuLes LiscenerkoLeLannochaveAaminurManagerPermiss1onkuLe• Settingsuse Jiminny Rules ListenerRoleRequiresListenerFeatureRule:N Sidekickuse Jiminny Actlons Updateuserkolesact1on:iM Slackuse Jiminny DiU koles userkolessvnculu:M Teaminsiahtsuse sentry'TimeMemoryMapperTranscrintionclass ScimprovisioningD TranscriptionSummaryM Twiliolpublic function construct.v MConferencoprivate readonly Dispatcher SeventDispatcher.› D ConferenceHandlerorivate readoniv UserService SuserService..MconferenceManager8) SoftPhoneManager.phgprivate readonly RoleChangeLogger SroleChangeLogger,private readonly RoleRepositoryInterface $roleRepository,ConferenceCallbackHandler.onpprivate readpoly eUndateU: Accept File 3- SXP Reject lAferR9lesAqti gor 5 files →@ conferenceManager.phpD1...}Local ChanaesConsole X• Chances 8 tlles, uodatino...= env.local apo→ E Side-by-side viewer@cb4ebf0c config/logging.php@ Constants.php app/Component/SCiMl(C) CoreUserRequest.oho aoo/DTO/SCIMIAAD/RequestiIdnivent =slennonloa!@JiminnvDebuaCommand.phn app/Console/Comma"Level → env "Lub Level', "Into'),php loadina,oho confid@ ScimProvisionina.ohn ann/Comnonent/SCIM'path' => storage_path('logs/Laravel.log').@) SoftPhoneManager.php app/Component/Twilio/Conference/ConferenceManag@ TeytMessaginaService.nhn ann/Services/TelenhonvUnversioned Files 11 files)= .env.nikilocal appenv.other ann(8 CanAcceccAiDonorteTact nhn toctell Init/Doliciod© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/Rf fovicon icn nubliFide tut and0 lictenerDoleCannotHaveAdminOrManagerPermissionRule.php app/RulesT raw sal_query.sal app© RoleAttr.php app/Component/SCIM/Mutators/Attributes/User(@) Cimulot-Wohhaskof.mmond.nhnonnlf.nodlalf.mmondolfrm/LuhonntWorkcnace accociated with hranch 'macter' hac heon rectored /l Pollback II Confiaure (17 minutes aaol=custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]A console [STAGING] X556557=562Accept Reject— 564— 565568=579Tx: Auto vTe cri CouT Luura qlOnE TanU UEULaVUUUK LU E 1D.select * from teams:SELECT r.* FROM automated_reports rjoin teams t on r.team.id = t.idWHERE r.freguency = 'daily'and r.status = 1AND t.status = 'active'AND (r.expires_at >= now OR r.expires_at IS NULL);select * from automated_report_results where report id IN (18, 33):select * from users where team_id = 1 and id = 1047:SELECT * FROM social_accounts WHERE sociable_id = 1047;select x rron aculvity searches where 10 = 10702select * trom activity search tilters where activity search 10 = 109521select * tromorder by 10 descorder by id desc;automated reports where 10 IN (55* from automated report results where id IN (81):select * trom users where 1d IN 00055,15787,11985071select * trom users where qroup 10 In (5/00:SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROMIautomated_report_results WHERE uuid_to_bin( 582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;select * from teams:Current vercion• suppont Dally • In 23 m100% 2• Mon 18 May 14:37:38AskJiminnyReportActivityServiceTest v& console [PROD]& console [EU]CascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSClM Role Manager+0 ..Go jiminny_jupiterBISBIS XIA VScimProvisioning.phpThought for 1s>610 tasks done• Update ScimProvisioning to handle roles during user creation* Add validation for SCIM role assignment (listener + admin/manager restriction)Thought for 1sListenerRoleCannotHlaveAdmRoleAttr.ono• RoleAttr.phpScimProvisioning.php) +40|Ask anvthina (%4L)+ @code SWE-1.6Reject allAccept all1ditterenceAAAAMNO'driver' => 'errorlog','level' => env('LOG_LEVEL', 'info'),'path' => storage_path('logs/Laravel.log').'custom channel' => ['driver' => 'single','path' => storage_path('loqs/custom.10g')'level' => env('LOG LEVEL', 'info').W Windsurf Toams 20-1UTF.8io 4 spaces...
|
NULL
|
4653352124179014207
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhostormVIewINavicarecodeLaravelKeractorFV faVsco. PhostormVIewINavicarecodeLaravelKeractorFV faVsco.js°9 master kProiect© SoftPhoneManager.php© PhoneNumberSecondaryAttr.phC CoreUserRequest.phpscimProvistoning.onpx© PrimaryEmailAttr.php© TextMessagingService.php© RoleAttr.php© SecondaryEmailAttr.phpuse Jiminny DTO\SCIM\AAD \Request \GetUserByQuery:© TitleAttr.phpc usernameAuur.onouse Jiminny DTO\SCIM\AAD \Request \PatchGroup;use Jiminny \Events\Users\UserCreated;© GroupMutator.phpuse Jiminny Models \Group;C UserMutator.phpuse Jiminny Models\JobTitle;c) GroupPatchOperation.phpuse Jiminny Models kole.C) UserPatchOperation.phpuse Jiminny Modets rean,c) constants.ohpuse Jiminny Modeusluser@ Sciminterface.phpuse Jiminny services userservice.c) ScimProvisionina.onouse szninny concracts Act kolekepostcoryencerraceSeedenuse Lulumanare supporc racades valzdacor.Sentryuse Jiminny Rules DependentRolesRule:17 Serializenuse Jiminny kuLes LiscenerkoLeLannochaveAaminurManagerPermiss1onkuLe• Settingsuse Jiminny Rules ListenerRoleRequiresListenerFeatureRule:N Sidekickuse Jiminny Actlons Updateuserkolesact1on:iM Slackuse Jiminny DiU koles userkolessvnculu:M Teaminsiahtsuse sentry'TimeMemoryMapperTranscrintionclass ScimprovisioningD TranscriptionSummaryM Twiliolpublic function construct.v MConferencoprivate readonly Dispatcher SeventDispatcher.› D ConferenceHandlerorivate readoniv UserService SuserService..MconferenceManager8) SoftPhoneManager.phgprivate readonly RoleChangeLogger SroleChangeLogger,private readonly RoleRepositoryInterface $roleRepository,ConferenceCallbackHandler.onpprivate readpoly eUndateU: Accept File 3- SXP Reject lAferR9lesAqti gor 5 files →@ conferenceManager.phpD1...}Local ChanaesConsole X• Chances 8 tlles, uodatino...= env.local apo→ E Side-by-side viewer@cb4ebf0c config/logging.php@ Constants.php app/Component/SCiMl(C) CoreUserRequest.oho aoo/DTO/SCIMIAAD/RequestiIdnivent =slennonloa!@JiminnvDebuaCommand.phn app/Console/Comma"Level → env "Lub Level', "Into'),php loadina,oho confid@ ScimProvisionina.ohn ann/Comnonent/SCIM'path' => storage_path('logs/Laravel.log').@) SoftPhoneManager.php app/Component/Twilio/Conference/ConferenceManag@ TeytMessaginaService.nhn ann/Services/TelenhonvUnversioned Files 11 files)= .env.nikilocal appenv.other ann(8 CanAcceccAiDonorteTact nhn toctell Init/Doliciod© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/Rf fovicon icn nubliFide tut and0 lictenerDoleCannotHaveAdminOrManagerPermissionRule.php app/RulesT raw sal_query.sal app© RoleAttr.php app/Component/SCIM/Mutators/Attributes/User(@) Cimulot-Wohhaskof.mmond.nhnonnlf.nodlalf.mmondolfrm/LuhonntWorkcnace accociated with hranch 'macter' hac heon rectored /l Pollback II Confiaure (17 minutes aaol=custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]A console [STAGING] X556557=562Accept Reject— 564— 565568=579Tx: Auto vTe cri CouT Luura qlOnE TanU UEULaVUUUK LU E 1D.select * from teams:SELECT r.* FROM automated_reports rjoin teams t on r.team.id = t.idWHERE r.freguency = 'daily'and r.status = 1AND t.status = 'active'AND (r.expires_at >= now OR r.expires_at IS NULL);select * from automated_report_results where report id IN (18, 33):select * from users where team_id = 1 and id = 1047:SELECT * FROM social_accounts WHERE sociable_id = 1047;select x rron aculvity searches where 10 = 10702select * trom activity search tilters where activity search 10 = 109521select * tromorder by 10 descorder by id desc;automated reports where 10 IN (55* from automated report results where id IN (81):select * trom users where 1d IN 00055,15787,11985071select * trom users where qroup 10 In (5/00:SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROMIautomated_report_results WHERE uuid_to_bin( 582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;select * from teams:Current vercion• suppont Dally • In 23 m100% 2• Mon 18 May 14:37:38AskJiminnyReportActivityServiceTest v& console [PROD]& console [EU]CascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSClM Role Manager+0 ..Go jiminny_jupiterBISBIS XIA VScimProvisioning.phpThought for 1s>610 tasks done• Update ScimProvisioning to handle roles during user creation* Add validation for SCIM role assignment (listener + admin/manager restriction)Thought for 1sListenerRoleCannotHlaveAdmRoleAttr.ono• RoleAttr.phpScimProvisioning.php) +40|Ask anvthina (%4L)+ @code SWE-1.6Reject allAccept all1ditterenceAAAAMNO'driver' => 'errorlog','level' => env('LOG_LEVEL', 'info'),'path' => storage_path('logs/Laravel.log').'custom channel' => ['driver' => 'single','path' => storage_path('loqs/custom.10g')'level' => env('LOG LEVEL', 'info').W Windsurf Toams 20-1UTF.8io 4 spaces...
|
53097
|
NULL
|
NULL
|
NULL
|
|
53100
|
1860
|
8
|
2026-05-18T11:37:59.445097+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779104279445_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2796147080355312063
|
-8636637127315567163
|
idle
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
SlackFileEditViewGoHistoryWindowHelpEU (DOCKERDOCKER (docker-compose)81DEV (docker)₴2asticsearchNo Livingconnections1 {"type" : "log""@timestamp":"2026-05-18T11:37:51Z", "tags" : ["error"ticsearch", "data"],"pid" :7, "message" : "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearch elasticsearch:9200"}1 {"type": "log","data"],,"@timestamp"'2026-05-18T11:37:51Z'tags": ["error""pid" :7, "message" :"[ConnectionError]: getaddrinfo ENOTFOUND elasticseelasticsearch:9200"}{"type" : "log""@timestamp": "2026-05-18T11:37:52Z", "tags" : ["warning"asticsearch","data"], "pid" :7, "message" : "Unablerevive connection: [URL_WITH_CREDENTIALS] : "2026-05-18T11:37:52Z"asticsearch", "data"],'"pid":7, "message": "No livingconnections"},"tags" : ["warning", "elkibana{"type" : "log","@timestamp" : "2026-05-18T11:37:52Z", "tags" : ["error", "plugins""taskManager""taskManager"], "pid":7, "message": "Failed to poll for work: Error: NoLivingconnections"}kibana1 {"type" : "log", "@timestamp" : "2026-05-18T11:37:54Z" , "tags" : ["error", "elasticsearch","data"],"pid":7, "message" :"[ConnectionError]: getaddrinfo ENOTFOUND elasticsearch elasticsearch:9200"}kibana1 {"type" : "log""@timestamp" : "2026-05-18T11:37:55Z" , "tags" : ["warning", "elasticsearch", "data"], "pid" :7,"message": "Unable to revive connection: [URL_WITH_CREDENTIALS] : "2026-05-18T11:37:55Z","tags" : ["warning", "elasticsearch", "data"], "pid" :7, "message"• "No livingconnections"}kibana1 {"type" : "log""@timestamp": "2026-05-18T11:37:55Z""tags" : ["error", "plugins", "taskManager""taskManager"], "pid":7, "message":"Failed to pollfor work: Error: NoLiving connections"}kibana1 {"type" : "log"ticsearch","data"],"@timestamp" : "2026-05-18T11:37:56Z", "tags" : ["error","elas"pid":7, "message":"[ConnectionError]: getaddrinfo ENOTFOUND elasticsearchelasticsearch: 9200"}docker_lamp_12026-05-18 11:37:45 Running ['artisan' mailbox:skip-lists:refresh] 12s DONEdocker_lamp_11/fd/1'1 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh > */proc/1 {"type" : "log""@timestamp": "2026-05-18T11:37:58Z", "tags" : ["warning"asticsearch", "data"], "pid":7, "message" : "Unableto revive connection: [URL_WITH_CREDENTIALS] :"2026-05-18T11:37:58Z"asticsearch", "data"], "pid":7, "message": "No living connections"}kibana1 {"type": "log", "@timestamp": "2026-05-18T11:37:58Z", "tags" : ["error", "plugins", "taskManager",,"taskManager"],"pid" :7,"message": "Failed to poll for work: Error: NoLiving connections"}View in Docker Desktopo View ConfigEnable Watch•HomeDMsActivityFilesLaterMore-Jiminny ...Metrorrtence# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of_jimi...0 Direct messages. Nikolay YankovR. Aneliya Angelovaão Stefka Stoyanova. Stoyan Tomov€. Vasil Vasilev% Galya DimitrovaLa Todor Stamatov ". Mario GeorgievNikolay IvanovLo James Graham *2 Stoyan Tanev&. Steliyan Georgiev&e Petko KashinskiE. Lukas Kovalik y...AppsJira CloudToastSupport Daily • in 23 m100% <7Describe what you are looking forNikolay YankovMessagesAdd canvas@ Files• Add language |TodayCONNECT/SYNC SETTINGSImport Email Conversations'OLet's Get Started:8• Mon 18 May 14:37:586 0+Sign in with Googleне ме пускаNikolay Yankov 2:17 PMЕй сегаГОТОВОLukas Kovalik 2:26 PMоще ведньж и в СФNikolay Yankov 2:27 PMгТОТОвОLukas Kovalik 2:27 PMработи вечеNikolay Yankov 2:27 PMимаше ли нещо за фиксLukas Kovalik 2:28 PMтрябва да си вързан към SF да работиNikolay Yankov 2:28 PMaxaaaMessage Nikolay Yankov...
|
53098
|
NULL
|
NULL
|
NULL
|
|
53275
|
1871
|
8
|
2026-05-18T12:00:22.775536+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105622775_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.29521278,"height":1.0},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6608242639432631174
|
5529508263503171478
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53276
|
1871
|
9
|
2026-05-18T12:00:25.782690+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105625782_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6871675,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6988032,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.71043885,"top":0.123703115,"width":0.00930851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5159095835385562987
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
53275
|
NULL
|
NULL
|
NULL
|
|
53277
|
1870
|
9
|
2026-05-18T12:00:30.792765+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105630792_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5187215517464698470
|
-8348545152461722172
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
SlackFileEditViewGoHistoryWindowHelpEUDOCKERXIDOCKER (docker-compose)docker_lamp_1S DONEdocker_1amp_1/fd/1'2>&1881DEV (docker)7822026-05-18 12:00:15 Running ['artisan' dialers:monitor-activities]91 '/usr/local/bin/php' 'artisan' dialers:monitor-activities ›'/proc/11 {"type": "log", "@timestamp"2026-05-18T12:00:25Z""tags" : ["error""elast,"data"], "pid" :7, "message" : "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearelasticsearch:9200"}docker_lamp_12026-05-18 12:00:24 Running ['artisan' jiminny:monitor-social-accountsdocker_lamp_1roc/1/fd/1' 2>&11 '/usr/local/bin/php' 'artisan' jiminny:monitor-social-accounts › '/p1 {"type": "log", "@timestamp": "2026-05-18T12:00:27Z", "tags" : ["warning"sticsearch", "data"], "pid" :7, "message": "Unable to revive connection: [URL_WITH_CREDENTIALS] "2026-05-18T12:00:27Z","tags" : ["warning", "elasticsearch", "data"], "pid" :7, "message" : "No livingconnections"}kibana1 {"type": "log""@timestamp" : "2026-05-18T12:00:27Z", "tags" : ["error", "plugins", "taskManager", "taskManager"], "pid" :7, "message": "Failed to poll for work: Error: No Livingconnections"}kibanaicsearch".1 {"type": "log""@timestamp": "2026-05-18T12:00:27Z", "tags" : ["error","elast"data"], "pid" :7,"message": "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearch elasticsearch:9200"}docker_lamp_12026-05-18 12:00:26 Running ['artisan' mailbox:skip-lists:refresh] . 1S DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/1/fd/1' 2>&1docker_lamp_112026-05-18 12:00:28 Running ['artisan'mailbox:batch:process --max-batches=15]1s DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=15 > */proc/1/fd/1' 2>&1I {"type" : "log", "@timestamp" : "2026-05-18T12:00:30Z","tags" : ["error", "elast,"data"], "pid" :7, "message" : "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearch elasticsearch:9200"}1 {"type" : "log""@timestamp": "2026-05-18T12:00:30Z""tags" : ["warning"sticsearch", "data"], "pid":7, "message" : "Unable to revive connection: [URL_WITH_CREDENTIALS] : "2026-05-18T12:00:30Z","tags" : ["warning", "elasticsearch", "data"], "pid" :7, "message" : "No living connections"}1 {"type": "log", "@timestamp" : "2026-05-18T12:00:30Z","tags" : ["error", "plugi, "taskManager""taskManager"], "pid":7, "message": "Failed to poll for work: Error: No Livingconnections"}View in Docker Desktopo View ConfigEnable WatchHomeDMsActivityFilesLaterMore-→Jiminny ...MetromrenCE# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of_jimi...0 Direct messages. Nikolay YankovR. Aneliya Angelovaão Stefka Stoyanova. Stoyan Tomov€. Vasil VasilevGalya DimitrovaLe Todor Stamatov "NMario Georgiev. Nikolay IvanovLo James Graham *8 Stoyan Tanev&. Steliyan Georgiev&e Petko KashinskiLukas Kovalik y…..AppsJira CloudToastGoogle Cale...Support Daily - now100% <78• Mon 18 May 15:00:30Describe what you are looking forNikolay Yankov6 0•Messagest Add canvasO Files+Todayне ме пускаNikolay Yankov 2:17 PMЕй сегаГОТОВОLukas Kovalik 2:26 PMоще ведньж и в СФNikolay Yankov 2:27 PMГТОТОвОLukas Kovalik 2:27 PMработи вечеNikolay Yankov 2:27 PMимаше ли нещо за фиксLukas Kovalik 2:28 PMтрябва да си вързан към SF да работиNikolay Yankov 2:28 PMaxaaaNikolay Yankov 2:41 PMимаме approve на PRда го даваме за QA?Lukas Kovalik 2:42 PMдаMessage Nikolay Yankov...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53278
|
1871
|
10
|
2026-05-18T12:00:30.829986+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105630829_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7429716278976468786
|
-8636355650190325311
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
PhostormVIewINavigarecodeLaravelKeractorFV faVsco.js°9 master kProledeyC ActivityController.ongC. BaseService.onp© SoftPhoneManager.php© PhoneNumberSecondaryAttr.phcoreuserkequest.onp© ScimProvisioning.php x © CoreUser.php© PrimaryEmailAttr.php© RoleAttr.php© SecondaryEmailAttr.phpn lictonorDoloCannotllavo AdminOriar© TitleAttr.php© UsernameAttr.phpclass Sc1mProv1s10n1ng© GroupMutator.phpC UserMutator.php207220public function patchGroupOperation(PatchGroup $dto, Team $team, Group Sgroup): boolf...}©) GroupPatchOperation.phppublic function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder{...558©) UserPatchOperation.phpc) constants.ohpScimintertace.ohppublic function create0rUpdateNewUser(CoreUserRequest $dto, Team $team): ?User{...}c) ScimProvisionina.onoSeeden7 Sentryprivate function isValidPhone(?string Snumber, string $countryCode): boolf...}17 Serializen• SettingsN Sidekickprivate function assignRolesFromScim(User Suser. CoreUserRequest $dto, Team Stean Accept RejectiM SlackM TeaminsiahtsSrequestedRoles = $dto->qetRolesO:N TimeMemorvMannerTranscrintionif (emptv(SrequestedRoles)) 4D TranscriptionSummaryM Twilicif (! $user->roles()->exists0) {User::ROLE ANALYSTOSv MConferenco/** @var Role Srole */› D ConferenceHandlersrole = Role: : quervo ->whered"name' => User: *ROLE ANALYSTD->FirstOr5a1.0vmConforoncoManador4) SoftPhoneManager.phpSthis->roleChangeLogger->1000M ConferenceCallbackHandler.onpactivellser: null@ ConferenceManager.phpaffected: Suser.>ODTO>C Event>0 Exceptioni Job> M Resolverrole: Srole,tvne• Sucen-swacRecentlvCnpated? RoleChangeType::CREATE_USER: RoleChangeType::ADD_ROLE,conteyt• PoleChanaetonteyt.•scтM.a Service>Gvo© TwilioConstants.onoCTwilioRepositorv.ohorecurnhUoloadenM UrlGeneratonD Utilitym UuidlSvisibleRoles = Sthis->roleRepository->findAl1ByTeam($team->qetIdO):M WaveformSroleIds = [1N Wehhooksforeach (SrequestedRoles as SroleName) {N Workflow> M ConfiaurationIm Concalom Commando350if (Srole === null){M ActivitiodM AnaivtincAccept File &+X Reject File 48€+5 of 8 files →ScoleIdsll = Srole->aetIdoled with hranch 'macter' hac heon rectored Il Pollback II Confiaure (40 minutes aao)=custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]A console [STAGING] X554555556568562564566-570 v57157757857958. Tx: Autovwhere crm_configuration_id = 1 and pl.playbook_id = 175:SELECT r.* FROM automated_reports rjoin teams t on r.team.id = t.idWHERE r.frequency = 'daily'ANU C.SCacUS = 'acuive'AND (r.expires.at >= now() OR r.expires.at IS NULL);automated_report_results where report id IN (18, 33):select * from users where team_id = 1 and id = 1047;SELE * FROMIsochal accounts WHERE soctable 1d = 1047select * from activitv searches where 1d = 10932:select * from activity_search_filters where activity_search_id = 10932;select * fromautomated_reports order by id desc;select * from automated_report_results order by id desc;select * from automated_reports where id IN (55);select * from automated_report_results where id IN (81);select * from users where id IN (10633, 13987, 11985);select * from users where group_id IN (3710);SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuidselect * from teams;select * from accounts where team_id = 1:select * trom automated report results where media type = "pdt' and status = 2SELECT * FROM automated_ report results WHERE uuid to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuidselect * from teams where id = 1029;select * fromcrm_configurations where provider = 'pipedrive':SELECTCONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_idsa.*t.owner id FROM social accounts saJJouN users u on u.id = sa.sociable idiWHERs mteam 1d = 1020 and sa.nroviden = Ininednivel."usen idl. "23460 ownen)""email". "inteanation-accountAninednive.jiminnv.com"."idi. kosupoont Dally • now100% S2• Mon 18 May 15:00:30U AskJiminnyReportActivityServiceTest v& console [PROD]# console [euyCascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSClM Role Manageme+0 ..Go jiminny_jupiterinp on Line019 A19 V 17 ^WARN Metadata found iin doc-comment for method9/ 10 tacke doneWrite unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META ROLES and USER_PATCH_ ATTR_ ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabled•Listener role cannot de comolned with aamin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintearationposwtn chaten vapp/Component/SClM/ Constants.php +3app/Component/SCIM/ ® ScimProvisioning.php +85-15nse/ CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ueer/M PoleAttr.nhn +17-ites/Userl ẞ RoleAttrTest.ohn +224* Reiect alliiAccent alliAsk anvthing 884-D)« Code SWF-1.6W Windsurf Teams 1:1 UTF-8io 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53279
|
1871
|
11
|
2026-05-18T12:00:33.559695+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105633559_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7684351733127023808
|
5529508263436062615
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results...
|
53278
|
NULL
|
NULL
|
NULL
|
|
53280
|
1870
|
10
|
2026-05-18T12:00:33.061973+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105633061_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2796147080355312063
|
-8636637127315567163
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
SlackFileEditViewGoHistoryWindowHelpEUDOCKERXIDOCKER (docker-compose)docker_lamp_1]1s DONEdocker_1amp_1roc/1/fd/1' 2>&1881DEV (docker)7822026-05-18 12:00:24 Running ['artisan'jiminny:monitor-social-accounts1 '/usr/local/bin/php' 'artisan'jiminny:monitor-social-accounts >*/p1 {"type": "log", "@timestamp": "2026-05-18T12:00:272"tags" : ["warning)sticsearch", "data"], "pid" :7, "message" : "Unable to revive connection: [URL_WITH_CREDENTIALS] : "2026-05-18T12:00:27Z" , "tags" : ["warning" , "elasticsearch","data"], "pid" :7, "message" : "No livingconnections"}{"type" : "log""@timestamp":"2026-05-18T12:00:27Z""taskManager"connections"}"taskManager"], "pid" :7,'"message": "Failed to poll"tags" : ["error", "plugifor work: Error: No Li1 {"type": "log", "@timestamp" : "2026-05-18T12:00:27Z", "tags" : ["error"icsearch","data"],,"elast"pid":7, "message": "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearchelasticsearch: 9200"}docker_lamp_12026-05-18 12:00:26 Running ['artisan' mailbox:skip-lists:refresh] . 1S DONEdocker_lamp_1 | l '/usr/local/bin/php' 'artisan' mailbox:skip-lists:refresh › */proc/1/fd/1' 2>&1docker_lamp_12026-05-18 12:00:28 Running ['artisan'mailbox: batch:process --max-batches=15]1s DONEdocker_lamp_11 '/usr/local/bin/php' 'artisan'mailbox:batch:process --max-batches=15 > '/proc/1/fd/1' 2>&11 {"type" : "log","@timestamp": "2026-05-18T12:00:30Z","tags" : ["error","elasticsearch", "data"], "pid" :7,"message": "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearch elasticsearch: 9200"}kibana{"type" : "log","@timestamp": "2026-05-18T12:00:30Z", "tags" : ["warning","elasticsearch", "data"], "pid":7, "message" : "Unable to revive connection: [URL_WITH_CREDENTIALS] : "2026-05-18T12:00:30Z", "tags" : ["warning"sticsearch", "data"],"pid" :7, "message": "No living connections"}kibana1 {"type" : "log"."@timestamp": "2026-05-18T12:00:30Z""tags" : ["error"ns","taskManager""taskManager"], "pid" :7, "message" : "Failedto poll for work: Error: No Livingconnections"}docker_lamp_12026-05-18 12:00:29 Running ['artisan' conference:monitor:count]... 4S DONEdocker_1amp_11 '/usr/local/bin/php' 'artisan' conference:monitor:count > '/proc/1/fd/1' 2>&1kibana1 {"type": "log", "@timestamp": "2026-05-18T12:00:32Z", "tags" : ["error"icsearch", "data"],,"elast"pid" :7, "message" : "[ConnectionError]: getaddrinfo ENOTFOUND elasticsearchelasticsearch:9200"}View in Docker Desktopo View ConfigEnable WatchHomeDMsActivityFilesLaterMore-→Jiminny ...Metrotrtencee# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of_jimi...0 Direct messages. Nikolay YankovR. Aneliya Angelovaão Stefka Stoyanova. Stoyan Tomov€. Vasil VasilevGalya DimitrovaLe Todor Stamatov "NMario Georgiev. Nikolay IvanovLo James Graham *8 Stoyan Tanev&. Steliyan Georgiev&e Petko KashinskiE. Lukas Kovalik y…..AppsJira CloudToastGoogle Cale...Support Daily • now100% <78• Mon 18 May 15:00:32Describe what you are looking forNikolay Yankov6 0•Messagest Add canvasO Files+Todayне ме пускаNikolay Yankov 2:17 PMЕй сегаГОТОВОLukas Kovalik 2:26 PMоще ведньж и в СФNikolay Yankov 2:27 PMГТОТОвОLukas Kovalik 2:27 PMработи вечеNikolay Yankov 2:27 PMимаше ли нещо за фиксLukas Kovalik 2:28 PMтрябва да си вързан към SF да работиNikolay Yankov 2:28 PMaxaaaNikolay Yankov 2:41 PMимаме approve на PRда го даваме за QA?Lukas Kovalik 2:42 PMдаMessage Nikolay Yankov...
|
53277
|
NULL
|
NULL
|
NULL
|
|
53347
|
1871
|
44
|
2026-05-18T12:03:11.553656+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105791553_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6871675,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6988032,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.71043885,"top":0.123703115,"width":0.00930851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5159095835385562987
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53348
|
1870
|
45
|
2026-05-18T12:03:18.234532+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105798234_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEdit→ GViewHistoryBookmarksProfilesTool FirefoxFileEdit→ GViewHistoryBookmarksProfilesToolsWindowHelpmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.com>0.Support Daily - now100% C47 8• Mon 18 May 15:03:17I1 [EMAIL] account+Lukas Kovalik[Platform] RefinementNikolay Yankov is in this call*J Use Gemini to take notesShare notes and transcriptStartJoin nowOther ways to join~{ MacBook Pro…..4 System Defa...• FaceTime HD...g Backgrounds...Gemini is available in Meet as your personal in-meeting assistant. It can analyze conversation via temporaryaccess to meeting captions. Using Ask Gemini won't create a recording or store meeting data. The meetinghost can turn it off. Learn moreLộ3...
|
NULL
|
1515535956893982221
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEdit→ GViewHistoryBookmarksProfilesTool FirefoxFileEdit→ GViewHistoryBookmarksProfilesToolsWindowHelpmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.com>0.Support Daily - now100% C47 8• Mon 18 May 15:03:17I1 [EMAIL] account+Lukas Kovalik[Platform] RefinementNikolay Yankov is in this call*J Use Gemini to take notesShare notes and transcriptStartJoin nowOther ways to join~{ MacBook Pro…..4 System Defa...• FaceTime HD...g Backgrounds...Gemini is available in Meet as your personal in-meeting assistant. It can analyze conversation via temporaryaccess to meeting captions. Using Ask Gemini won't create a recording or store meeting data. The meetinghost can turn it off. Learn moreLộ3...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53349
|
1871
|
45
|
2026-05-18T12:03:18.229770+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105798229_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormVIewINavigarecodeLaravelKeractorFV faVsco. PhostormVIewINavigarecodeLaravelKeractorFV faVsco.js°9 master k >Project© BaseService.php© PhoneNumberSecondary Attr.pr© PrimaryEmailAttr.phpcoreuserkequest.onp© RoleAttr.php© SecondaryEmailAttr.phpn lictonorDoloCannotllavoAdminOria© TitleAttr.php© UsernameAttr.php© GroupMutator.phpC UserMutator.php51&© SoftPhoneManager.php© ScimProvisioning.php x © CoreUser.phpclass Sc1mProv1s10n1ngpublic function create0rUpdateNewUser (CoreUserRequest Sdto, Team Stean): PUserc) GroupPatchOperation.phpC) UserPatchOperation.phpc) constants.ohpScimintertace.ohpc) ScimProvisionina.onoSeeden• Sentry17 SerializenSettingsN SidekickD Slack• TimeMemoryMapperD TranscriptionTranscriptionSummaryM Twilicv D Conference› D ConferenceHandler~ D ConferenceManager4) SoftPhoneManager.php©ConferenceCallbackHandler.php@ ConferenceManager.php> DDTO>C Event> D ExceptionDJob• _ Resolvera Service>Gvo© TwilioConstants.onoC TwilioRepositorv.ohoUoloadenM UrlGeneratonDUtilitym Uuidl• WaveformN WehhooksN Workflowif (! SnewUser->roles(-›existsO) ‹$newUser->addRole(User: :ROLE_ANALYST);Role: : query() ->where(['name' => User: :ROLE_ANALYST])->first0rFail();$this->roleChangeLoggger->LogSnewUser,vole.type$newUser->wasRecentlyCreated:koLecnancelype..ukcAlt uockkoLechangelype:: AUD RULt,context: rolecnancelontext..scm$this->assignRolesFromScim($newUser, $dto, $team);if (! empty($dto->getTitle())) €$jobTitle = Steam->jobs() ->where('name' , $dto-›getTitle())->first();if ($jobTitle instanceof JobTitle) ElSnewUser->update(l'job_title_id' => $jobTitle-›getId(]);1 else {** dvar Joblitle SnewJobTitle *SnewJobTitle = Steam->jobs() ->create(["name' = Soto->oetTitle@.SnewUser->update(['Job_title_id' => $newJobTitle->getIdOI);if ($newUser-›wasRecentlyCreated) {$this-›eventDispatcher->dispatch(new UserCreated($newUser));return $newUser;j catch (Exception Sexception) (sencry:.caprurecxcepczonsexcepc1onreturn nuul:> M ConfiaurationD Consolem Commando> Activities> C Analytics305private functiton isVatddPHond v Accept File %- eX Rejectifite $ecuntre C5 de) fileoot (..-ed with hranch 'macter' hac heon rectored Il Pollback II Confiaure (12 minutes aaolE custom.logE laravel.log4 SF [jiminny@localhost]A HS_Jocal [jiminny@localhost]A console [STAGING]X•.0 .Tx: Autovwhere crm_configuration_id = 1 and pl.playbook_id = 175;A console [PROD]# console [euyS. jiminny_jupiter019 A19 V17 ^554555556557558559I-560-561562563568569570v select * from teams;SELECT r.* FROM automated_reportsrjoin teams t on r.teamaid = t.idWHERE r.frequency = "daily'AND t.status = 'active'AND (r.expices.at >= now() OR r.expices._at IS NULL);automated_report_results where report. id IN (18, 33);select * from users where team_id = 1 and id = 1047;social_accounts WHERE sociable_id = 1047;select * from activity_searches where id = 10932;select * from activity_search_filters where activity_search_id = 10932;select * fromautomated_reports order by id desc;select * from automated_report_results order by id desc;select * from automated_reports where id IN (55);select * from automated_report_results where id IN (81);select * from users where id IN (10633, 13987, 11985);select * from users where group_id IN (3710);SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin(^582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;select * from teams;select * from accounts where team_id = 1;select * from automated_report_results where media type = 'pdf' and status = 2;SELECT * FROM automated_report_results WHERE uuid_to_bin(^82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;select * from teams where id = 1029;select * fromcrm_configurations where provider = 'pipedrive";SELECTCONCAT(u.id, CASE WHEN U.id = t.owner_id THEN ' (owner)' ELSE "' END) AS user_id,sa.*,t.owner_id FROM social_accounts saWHERE U.team_id = 1029 and sa.provider = 'pipedrive';"usen idl. "23460 ownen)""email". "inteanation-accountaninednive.jiminnv.com"supoont Dally • now100% S2• Mon 18 May 15:03:17U AskJiminnyReportActivityServiceTest~CascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..php on LineWARN Metadata found in doc-comment for method9 / 10 tasks done :Write unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META_ROLES and USER_PATCH_ATTR_ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabledl• Listener role cannot be combined with admin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintegration.app/Component/SClM/ Constants.php +3app/Component/SCIM/ ScimProvisioning.php +85-15nse/D CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ucer/M PoleAttr.nho 417ites/Userl ẞ RoleAttrTest.ohn +224Ask anvthing 884-D)« Code SWF-1.6* Reiect alliiAccent alliW Windsurf Teams 282:53 UTF-8f 4 spaces...
|
NULL
|
-1616471670776694782
|
NULL
|
click
|
ocr
|
NULL
|
PhostormVIewINavigarecodeLaravelKeractorFV faVsco. PhostormVIewINavigarecodeLaravelKeractorFV faVsco.js°9 master k >Project© BaseService.php© PhoneNumberSecondary Attr.pr© PrimaryEmailAttr.phpcoreuserkequest.onp© RoleAttr.php© SecondaryEmailAttr.phpn lictonorDoloCannotllavoAdminOria© TitleAttr.php© UsernameAttr.php© GroupMutator.phpC UserMutator.php51&© SoftPhoneManager.php© ScimProvisioning.php x © CoreUser.phpclass Sc1mProv1s10n1ngpublic function create0rUpdateNewUser (CoreUserRequest Sdto, Team Stean): PUserc) GroupPatchOperation.phpC) UserPatchOperation.phpc) constants.ohpScimintertace.ohpc) ScimProvisionina.onoSeeden• Sentry17 SerializenSettingsN SidekickD Slack• TimeMemoryMapperD TranscriptionTranscriptionSummaryM Twilicv D Conference› D ConferenceHandler~ D ConferenceManager4) SoftPhoneManager.php©ConferenceCallbackHandler.php@ ConferenceManager.php> DDTO>C Event> D ExceptionDJob• _ Resolvera Service>Gvo© TwilioConstants.onoC TwilioRepositorv.ohoUoloadenM UrlGeneratonDUtilitym Uuidl• WaveformN WehhooksN Workflowif (! SnewUser->roles(-›existsO) ‹$newUser->addRole(User: :ROLE_ANALYST);Role: : query() ->where(['name' => User: :ROLE_ANALYST])->first0rFail();$this->roleChangeLoggger->LogSnewUser,vole.type$newUser->wasRecentlyCreated:koLecnancelype..ukcAlt uockkoLechangelype:: AUD RULt,context: rolecnancelontext..scm$this->assignRolesFromScim($newUser, $dto, $team);if (! empty($dto->getTitle())) €$jobTitle = Steam->jobs() ->where('name' , $dto-›getTitle())->first();if ($jobTitle instanceof JobTitle) ElSnewUser->update(l'job_title_id' => $jobTitle-›getId(]);1 else {** dvar Joblitle SnewJobTitle *SnewJobTitle = Steam->jobs() ->create(["name' = Soto->oetTitle@.SnewUser->update(['Job_title_id' => $newJobTitle->getIdOI);if ($newUser-›wasRecentlyCreated) {$this-›eventDispatcher->dispatch(new UserCreated($newUser));return $newUser;j catch (Exception Sexception) (sencry:.caprurecxcepczonsexcepc1onreturn nuul:> M ConfiaurationD Consolem Commando> Activities> C Analytics305private functiton isVatddPHond v Accept File %- eX Rejectifite $ecuntre C5 de) fileoot (..-ed with hranch 'macter' hac heon rectored Il Pollback II Confiaure (12 minutes aaolE custom.logE laravel.log4 SF [jiminny@localhost]A HS_Jocal [jiminny@localhost]A console [STAGING]X•.0 .Tx: Autovwhere crm_configuration_id = 1 and pl.playbook_id = 175;A console [PROD]# console [euyS. jiminny_jupiter019 A19 V17 ^554555556557558559I-560-561562563568569570v select * from teams;SELECT r.* FROM automated_reportsrjoin teams t on r.teamaid = t.idWHERE r.frequency = "daily'AND t.status = 'active'AND (r.expices.at >= now() OR r.expices._at IS NULL);automated_report_results where report. id IN (18, 33);select * from users where team_id = 1 and id = 1047;social_accounts WHERE sociable_id = 1047;select * from activity_searches where id = 10932;select * from activity_search_filters where activity_search_id = 10932;select * fromautomated_reports order by id desc;select * from automated_report_results order by id desc;select * from automated_reports where id IN (55);select * from automated_report_results where id IN (81);select * from users where id IN (10633, 13987, 11985);select * from users where group_id IN (3710);SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin(^582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;select * from teams;select * from accounts where team_id = 1;select * from automated_report_results where media type = 'pdf' and status = 2;SELECT * FROM automated_report_results WHERE uuid_to_bin(^82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;select * from teams where id = 1029;select * fromcrm_configurations where provider = 'pipedrive";SELECTCONCAT(u.id, CASE WHEN U.id = t.owner_id THEN ' (owner)' ELSE "' END) AS user_id,sa.*,t.owner_id FROM social_accounts saWHERE U.team_id = 1029 and sa.provider = 'pipedrive';"usen idl. "23460 ownen)""email". "inteanation-accountaninednive.jiminnv.com"supoont Dally • now100% S2• Mon 18 May 15:03:17U AskJiminnyReportActivityServiceTest~CascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..php on LineWARN Metadata found in doc-comment for method9 / 10 tasks done :Write unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META_ROLES and USER_PATCH_ATTR_ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabledl• Listener role cannot be combined with admin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintegration.app/Component/SClM/ Constants.php +3app/Component/SCIM/ ScimProvisioning.php +85-15nse/D CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ucer/M PoleAttr.nho 417ites/Userl ẞ RoleAttrTest.ohn +224Ask anvthing 884-D)« Code SWF-1.6* Reiect alliiAccent alliW Windsurf Teams 282:53 UTF-8f 4 spaces...
|
53347
|
NULL
|
NULL
|
NULL
|
|
53362
|
1871
|
53
|
2026-05-18T12:03:42.547476+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105822547_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.29521278,"height":1.0},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
775695417232670985
|
5527291647994408855
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
53360
|
NULL
|
NULL
|
NULL
|
|
53363
|
1871
|
54
|
2026-05-18T12:03:54.615865+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105834615_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6871675,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6988032,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.71043885,"top":0.123703115,"width":0.00930851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5137194390979529455
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53364
|
1871
|
55
|
2026-05-18T12:03:57.635051+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105837635_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
775695417232670985
|
5527291647994408855
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
53363
|
NULL
|
NULL
|
NULL
|
|
53365
|
1871
|
56
|
2026-05-18T12:04:00.675492+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105840675_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6871675,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6988032,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.71043885,"top":0.123703115,"width":0.00930851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7026725200314849403
|
5527256463622377366
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53366
|
1871
|
57
|
2026-05-18T12:04:09.836153+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105849836_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormVIewINavigarecodeLaravelRefactorJOOISWindo PhpStormVIewINavigarecodeLaravelRefactorJOOISWindowFV faVsco.js°9 master k >ProiectCActivityController.ongC BaseService.onp© SoftPhoneManager.phpg constants.ong• Scimintertace.ong(C) CoreUserRequest.onp© ScimProvisioning.php x © CoreUser.phpD Seederlextwessagingservice.pngW sentryW senlalizerSettingsSidekickW Slackaaiwillio• M Conference™ ConferenceHandlerC) SoftPhoneManader.ohd© ConferenceCallbackHandler.php© ConferenceManager.phpIMnTOTM EventD ExceptionD JobD Resolverm Corvico(c) TwilioConstants.onp© TwilioRepository.php0 Uploader0 UrlGeneratora Utility0 Uuid_ Waverorm_WeohooksM Workflow> M ConfigurationM Consolev CommandsM Activities>M AnalvticcM Calendarsv MCrmM HuhsnotD IntegrationApp• M TraitsC) Addl avoutEntities.nhnclass Sc1mProv1s10n1ngprivate function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): Acceptif (empty($requestedRoles)) {if (! Suser->rolesO->exists0) {$user->addRole( role: User::ROLE_ANALYST):© AutologDelayedCommand.php© BackfillOpportunityUserFromAccounto6 Pullborn Command Ahctrant nhn(e) RullbornDinaCommand nhn** dvar kole srole *Srole = Role::query@->where(['name' => User::ROLE_ANALYST])->first0rFailO:role: Sroletype: suser->wasRecentlyCreated? Rolechangelvoe: * CREATE USER: RoleChangeType::ADD_ROLE,$visibleRoles = $this->roleRepository->findAllByTeam($team->getId):$roleIds = 0]:foreach (SrequestedRoles as SroleName)$role = SvisibleRoles->firstWhere(key: 'name', SroleName):if (Srole === null) {SroleIds[] = Srole->qetIdO:if (emptv($roleIds)) $l'roles' => Srolelds],noles' =>naup aebendentRotes Accept Fle• X Reiect File +%@ + 50f8files →aco accociated with hranch 'macter' hac heon rectored Il Pollback II Confiaure (41 minutes aao)= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]X556statihTs Tx: AutovGo jiminny_jupiterwhere crm_configuration_id = 1 and pl.playbook_id = 175;019 A19 V17 ^ VSELECT r.* FROM automated_reports rJo1n ceams t on r.ceam 10 = t.10hckE r.trequency = "dallyAND C.SCacUS = 'aculveAND (r.expices.at >= now() OR r.expices._at IS NULL);automated_report_results where report id IN (18, 33);select * from users where team 1d = 1 and 1d = 1047sochal accounts WHEREsochable 10 = 1047select * from activity searches where 1d = 109325From activity search filters where activity search 1d = 109321omated renorts order by id descserect e from autonated reports ehentes ther 5automated_report_results where ia IN (81);=plect * from usens whene id TN (10633|13987, 11985):SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuidselecc * rron accouncs where ceam 10 = 1select * trom automated report results where media type = "pdt' and status = 2сciсст * EPOM automated report_resultsWHERE uuid to_ bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuidalaßtnamthomd mhanannselect * fromSELECTCONCATU. 1O, CASE WHEN U.1d E t.owner 10 THEN(owner) ' ELSE I1 END) AS user idt.owner id FROM social accounts s:JOuN users u on U.id= sa.sociable idiWHERs M.team 1d = 1020 and sa.nroviden = Ininednivel,Husen idil. "03460 (owner)"supoont Dally • now100% S2• Mon 18 May 15:04:09AskJiminnyReportActivityServiceTest vCascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..inp on LineWARN Metadata found iin doc-comment for method9/ 10 tacke doneWrite unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META ROLES and USER_PATCH_ATTR ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabled•LIstener role cannot de comolned with aamin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintearationposwtn chaten vapp/Component/SClM/ Constants.php +3app/Component/SCIM/ ® ScimProvisioning.php +85-15nse/ CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ueer/M PoleAttr.nhn +17-ites/Userl ẞ RoleAttrTest.ohn +224* Reiect alliiAccent alliAsk anvthina 884-L)« Code SWF-1.6W Windsurf Teams 1:1 UTF-8io 4 spaces...
|
NULL
|
8846095472131236878
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormVIewINavigarecodeLaravelRefactorJOOISWindo PhpStormVIewINavigarecodeLaravelRefactorJOOISWindowFV faVsco.js°9 master k >ProiectCActivityController.ongC BaseService.onp© SoftPhoneManager.phpg constants.ong• Scimintertace.ong(C) CoreUserRequest.onp© ScimProvisioning.php x © CoreUser.phpD Seederlextwessagingservice.pngW sentryW senlalizerSettingsSidekickW Slackaaiwillio• M Conference™ ConferenceHandlerC) SoftPhoneManader.ohd© ConferenceCallbackHandler.php© ConferenceManager.phpIMnTOTM EventD ExceptionD JobD Resolverm Corvico(c) TwilioConstants.onp© TwilioRepository.php0 Uploader0 UrlGeneratora Utility0 Uuid_ Waverorm_WeohooksM Workflow> M ConfigurationM Consolev CommandsM Activities>M AnalvticcM Calendarsv MCrmM HuhsnotD IntegrationApp• M TraitsC) Addl avoutEntities.nhnclass Sc1mProv1s10n1ngprivate function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): Acceptif (empty($requestedRoles)) {if (! Suser->rolesO->exists0) {$user->addRole( role: User::ROLE_ANALYST):© AutologDelayedCommand.php© BackfillOpportunityUserFromAccounto6 Pullborn Command Ahctrant nhn(e) RullbornDinaCommand nhn** dvar kole srole *Srole = Role::query@->where(['name' => User::ROLE_ANALYST])->first0rFailO:role: Sroletype: suser->wasRecentlyCreated? Rolechangelvoe: * CREATE USER: RoleChangeType::ADD_ROLE,$visibleRoles = $this->roleRepository->findAllByTeam($team->getId):$roleIds = 0]:foreach (SrequestedRoles as SroleName)$role = SvisibleRoles->firstWhere(key: 'name', SroleName):if (Srole === null) {SroleIds[] = Srole->qetIdO:if (emptv($roleIds)) $l'roles' => Srolelds],noles' =>naup aebendentRotes Accept Fle• X Reiect File +%@ + 50f8files →aco accociated with hranch 'macter' hac heon rectored Il Pollback II Confiaure (41 minutes aao)= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]X556statihTs Tx: AutovGo jiminny_jupiterwhere crm_configuration_id = 1 and pl.playbook_id = 175;019 A19 V17 ^ VSELECT r.* FROM automated_reports rJo1n ceams t on r.ceam 10 = t.10hckE r.trequency = "dallyAND C.SCacUS = 'aculveAND (r.expices.at >= now() OR r.expices._at IS NULL);automated_report_results where report id IN (18, 33);select * from users where team 1d = 1 and 1d = 1047sochal accounts WHEREsochable 10 = 1047select * from activity searches where 1d = 109325From activity search filters where activity search 1d = 109321omated renorts order by id descserect e from autonated reports ehentes ther 5automated_report_results where ia IN (81);=plect * from usens whene id TN (10633|13987, 11985):SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuidselecc * rron accouncs where ceam 10 = 1select * trom automated report results where media type = "pdt' and status = 2сciсст * EPOM automated report_resultsWHERE uuid to_ bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuidalaßtnamthomd mhanannselect * fromSELECTCONCATU. 1O, CASE WHEN U.1d E t.owner 10 THEN(owner) ' ELSE I1 END) AS user idt.owner id FROM social accounts s:JOuN users u on U.id= sa.sociable idiWHERs M.team 1d = 1020 and sa.nroviden = Ininednivel,Husen idil. "03460 (owner)"supoont Dally • now100% S2• Mon 18 May 15:04:09AskJiminnyReportActivityServiceTest vCascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..inp on LineWARN Metadata found iin doc-comment for method9/ 10 tacke doneWrite unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META ROLES and USER_PATCH_ATTR ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabled•LIstener role cannot de comolned with aamin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintearationposwtn chaten vapp/Component/SClM/ Constants.php +3app/Component/SCIM/ ® ScimProvisioning.php +85-15nse/ CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ueer/M PoleAttr.nhn +17-ites/Userl ẞ RoleAttrTest.ohn +224* Reiect alliiAccent alliAsk anvthina 884-L)« Code SWF-1.6W Windsurf Teams 1:1 UTF-8io 4 spaces...
|
53365
|
NULL
|
NULL
|
NULL
|
|
53367
|
1870
|
51
|
2026-05-18T12:04:12.838701+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105852838_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2240692385361527689
|
5529508263503171479
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53368
|
1871
|
58
|
2026-05-18T12:04:12.814936+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105852814_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6608242639432631174
|
5529508263503171478
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53402
|
1872
|
12
|
2026-05-18T12:05:23.147103+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105923147_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.comSupport Daily - now100% [8• Mon 18 May 15:05:224Nikolay YankovSteliyan GeorgievAneliya Angelova*Lukas Kovalik3:05 PM | [Platform] Refinement®...
|
NULL
|
-8692871385356982873
|
NULL
|
visual_change
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.comSupport Daily - now100% [8• Mon 18 May 15:05:224Nikolay YankovSteliyan GeorgievAneliya Angelova*Lukas Kovalik3:05 PM | [Platform] Refinement®...
|
53401
|
NULL
|
NULL
|
NULL
|
|
53403
|
1873
|
7
|
2026-05-18T12:05:24.079636+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105924079_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.42785904,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.43650267,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.4474734,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.45611703,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.46476063,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.47573137,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.4867021,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.51329786,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.5242686,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"bounds":{"left":0.69348407,"top":0.09896249,"width":0.04089096,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6871675,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.6988032,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.71043885,"top":0.123703115,"width":0.00930851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5137194390979529455
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53428
|
1872
|
28
|
2026-05-18T12:06:17.684884+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105977684_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4235983745889776938
|
-8204421443435123770
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
+FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpSupport Daily - now→Q.meet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.comNikolay Yankov (Presenting)FleEditTabM InboF Proje( AtterSchel© Cursc* Ciau:• Cost|app..| G Allow PipelZ UY-27 LJY-27 [JY-28• Mon 18 May 15:06(UY-2httos:/wminny.atiassian.net/browse/fY-20912l• SminnyD ProjectsE3 SSH• Home | Salestorce @ O 8 [I El Datadoo O ® # Ciaude3 CircleciA Sentry0 Tasks7 Insights & Coachin…0 Dev0D Al BookmarkaSearch+ CreateAsk Rovo® For you© Recent |# Starred8. AppsQ SpacesStarredS Service-DeskJiminny (Oid)Spaces/Imicey ONew) / && Ndd parent/A Jy-20912Fallback mechanism for users with active SF tokens for CRM Matching@1|Backlog*x Improve StoryDetailsDescriptionWe identified an issue for Tourlane where Twilio calls appear as "Unknown Customer" when the Salesforce admin connection token has expired. In this case, CRM object|matching fails because the system relies only on the admin's Salesforce token.We should implement the same fallback logic currently used for dialers - il the Salesforce admin token is expired or inactive, the system should search for another activeSalesforce token from any user within the same organisation and use il for CRM matching.Assignee& UnassignedAssign to meReporterB Adelina PetrovaJiminny (New)I CID Platform TeamD Enterprise Stability L...Acceptance Criteria:• If the Salesforce admin token has expired, the system searches for another active Salesforce token within the organisation.• CRM object matching continues successfully using the fallback token.• Calls should not appear as "Unknown Customer" when another valid Salesforce connection exists in the organisation.P Quick start developmentLink this work item to your code byincluding keys when creating abranch, commit, or pull requestbelow. Learn moreDismiss(ID SE Kanban= More spaces= Filters(B DashboardsOperationsSubtasksadd suotaskLinked work itemsDevelopmentQ Open with VS CodeIJ Create branchCreate commit |x Confiuence1: TeamsActivityPlatform18Work log% Customise sidebarSub-ProductAdd optionsAdd a comment….LabelsWho is working on this...?Status update.ThanksPro tip: press (M to comStory point est3:06 PM | [Platform] Refinement ®100% C8• Mon 18 May 15:06:175Nikolay YankoAneliya AngelovaINikolay IvanovLukas Kovalik...
|
53427
|
NULL
|
NULL
|
NULL
|
|
53429
|
1873
|
17
|
2026-05-18T12:06:18.027870+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779105978027_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormVIewINavigarecodeLaravelRefactorJOOISWindo PhpStormVIewINavigarecodeLaravelRefactorJOOISWindowFV faVsco.js?9 master k. vProiect vC ActivityController.ongC BaseService.onp© SoftPhoneManager.phpg constants.ong(C) CoreUserRequest.onpseimFrovistoning.onpx© CoreUser.php• Scimintertace.ongD SeederW sentryW senlalizerSettingsSidekickW Slackw Transcriptionaaiwillio• M Conference™ ConferenceHandler• M ConferenceManadeC) SoftPhoneManader.oho© ConferenceCallbackHandler.php© ConferenceManager.phpIMnTOTM Event0 ExceptionD JobTh Recolverm CorvicoDvO(c) TwilioConstants.onp© TwilioRepository.php0 Uploader0 UrlGeneratora Utility0 Uuid_ Waverorm_WeohooksM Workflow> M ConfigurationM Consolev CommandsM Activities>M AnalvticcCalendarsv MCrmM Huhsnotclass Sc1mProv1s10n1ngn assignRolesFromScim(User Suser, CoreUserRequest Sato, Team Stean): void['roles' => SroleIdsl."roles' =>'array")main: 1'0newDependentRolesPule(SvisibleRoles)inew ListenerRoleCannotHaveAdmin0rManagerPermissionRule($visibleRoles),'roles.*' => [anstinet""an.• SvisibleRoles->pluck( value: 'id')->implode( value: ',').new ListenerRoleRequiresListenerFeatureRule(Steam)if (Svalidator->fails0) {return?sroles = "viszoleroles->wheren key: "1d', Srolelds):Sdto = new UserRolesSvncdT0dactivelser: nulu.roles: Sroles.public function deleteGroup(Sgroup): boolf...}public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group{...}public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): GrcD IntegrationApp• M TraitsC) Addl avoutEntities.nhn© AutologDelayedCommand.php9 Pockfill@nnortunitvllcorSromAccountle RullbornCommand Ahctraat nhn(e) RullbornDinaCommand nhn1 1 of 4 edits JAccept File &+X Reject File 4%€+ 5 of 8 files →=laravel.log« SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING] X554555556557558'_563566-567568569570v || |593)Tx: AutovGo jiminny_jupiterwhere crm_configuration_id = 1 and pl.playbook_id = 175:GlS BIS XUAselect * from teamsSELECT r.* FROM automated_reports rjoin teams t on r.team id = t.idhckE r.trequency = "dallyAND t.status = 'active'AND (r.expires.at >= now() OR r.expires.at IS NULL);1 automated_report_results where report 1d IN (18, 339select * from users where team_id = 1 and id = 1047;SELE * FROMIsochal accounts WHERE soctable 10 = 10471select * from activity_searches where id = 10932•select *from activity_search_filters where activity_search_id = 10932;select * fromautomated_reports order by id desc;select * from automated_report_results order by id desc;select * from automated_reports where id IN (55);select * from automated_report_results where id IN (81);select * from users where id IN (10633, 13987, 11985);select * from users where group_id IN (3710);SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuidselect * from teams;select * from accounts where team_id = 1:select * trom automated report results where media type = "pdt' and status = 2SFLECT * FROM automated report results WHERE uuid_ to_ bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid)select * from teams where id = 1029;select * fromcrm_configurations where provider = 'pipedrive':SELECTCONCAT(u,id. CASE WHEN u.id = t.owner id THEN • (owner)' ELSE •• END) AS user idisa.*t.owner_id FROM social_accounts saJOIN users u on u.id = sa.sociable idWHEPE uteam id = 1029 and sa-nnoviden = 'ninednive'."usen idl. "23460 ownen)"supoont Dally • now100% 1• Mon 18 May 15:06:17AskJiminnyReportActivityServiceTest vCascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..inp on LineWARN Metadata found iin doc-comment for method9/ 10 tacke doneWrite unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META ROLES and USER_PATCH_ATTR_ ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabled•LIstener role cannot de comolned with aamin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintearationposwtn chaten vapp/Component/SClM/ Constants.php +3app/Component/SCIM/ ® ScimProvisioning.php +85-15nse/ CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ucer/M PoleAttr.nho 417ites/Userl ẞ RoleAttrTest.ohn +224* Reiect alliiAccent alliAsk anvthing 884-D)« Code SWF-1.6W Windsurf Teams 1:1 UTF-8io 4 spaces...
|
NULL
|
-8500886048129294954
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormVIewINavigarecodeLaravelRefactorJOOISWindo PhpStormVIewINavigarecodeLaravelRefactorJOOISWindowFV faVsco.js?9 master k. vProiect vC ActivityController.ongC BaseService.onp© SoftPhoneManager.phpg constants.ong(C) CoreUserRequest.onpseimFrovistoning.onpx© CoreUser.php• Scimintertace.ongD SeederW sentryW senlalizerSettingsSidekickW Slackw Transcriptionaaiwillio• M Conference™ ConferenceHandler• M ConferenceManadeC) SoftPhoneManader.oho© ConferenceCallbackHandler.php© ConferenceManager.phpIMnTOTM Event0 ExceptionD JobTh Recolverm CorvicoDvO(c) TwilioConstants.onp© TwilioRepository.php0 Uploader0 UrlGeneratora Utility0 Uuid_ Waverorm_WeohooksM Workflow> M ConfigurationM Consolev CommandsM Activities>M AnalvticcCalendarsv MCrmM Huhsnotclass Sc1mProv1s10n1ngn assignRolesFromScim(User Suser, CoreUserRequest Sato, Team Stean): void['roles' => SroleIdsl."roles' =>'array")main: 1'0newDependentRolesPule(SvisibleRoles)inew ListenerRoleCannotHaveAdmin0rManagerPermissionRule($visibleRoles),'roles.*' => [anstinet""an.• SvisibleRoles->pluck( value: 'id')->implode( value: ',').new ListenerRoleRequiresListenerFeatureRule(Steam)if (Svalidator->fails0) {return?sroles = "viszoleroles->wheren key: "1d', Srolelds):Sdto = new UserRolesSvncdT0dactivelser: nulu.roles: Sroles.public function deleteGroup(Sgroup): boolf...}public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group{...}public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): GrcD IntegrationApp• M TraitsC) Addl avoutEntities.nhn© AutologDelayedCommand.php9 Pockfill@nnortunitvllcorSromAccountle RullbornCommand Ahctraat nhn(e) RullbornDinaCommand nhn1 1 of 4 edits JAccept File &+X Reject File 4%€+ 5 of 8 files →=laravel.log« SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING] X554555556557558'_563566-567568569570v || |593)Tx: AutovGo jiminny_jupiterwhere crm_configuration_id = 1 and pl.playbook_id = 175:GlS BIS XUAselect * from teamsSELECT r.* FROM automated_reports rjoin teams t on r.team id = t.idhckE r.trequency = "dallyAND t.status = 'active'AND (r.expires.at >= now() OR r.expires.at IS NULL);1 automated_report_results where report 1d IN (18, 339select * from users where team_id = 1 and id = 1047;SELE * FROMIsochal accounts WHERE soctable 10 = 10471select * from activity_searches where id = 10932•select *from activity_search_filters where activity_search_id = 10932;select * fromautomated_reports order by id desc;select * from automated_report_results order by id desc;select * from automated_reports where id IN (55);select * from automated_report_results where id IN (81);select * from users where id IN (10633, 13987, 11985);select * from users where group_id IN (3710);SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuidselect * from teams;select * from accounts where team_id = 1:select * trom automated report results where media type = "pdt' and status = 2SFLECT * FROM automated report results WHERE uuid_ to_ bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid)select * from teams where id = 1029;select * fromcrm_configurations where provider = 'pipedrive':SELECTCONCAT(u,id. CASE WHEN u.id = t.owner id THEN • (owner)' ELSE •• END) AS user idisa.*t.owner_id FROM social_accounts saJOIN users u on u.id = sa.sociable idWHEPE uteam id = 1029 and sa-nnoviden = 'ninednive'."usen idl. "23460 ownen)"supoont Dally • now100% 1• Mon 18 May 15:06:17AskJiminnyReportActivityServiceTest vCascadeImplement Trial OwneFixing Redis Rate LimSalestorce Token FalliSCIM Role Manageme+0 ..inp on LineWARN Metadata found iin doc-comment for method9/ 10 tacke doneWrite unit tests for SCIM role management10) Contact Mario to vodate customer10 / 10 tasks doneselm role managementtor leamtallor has been successtully implemented. Here's what was completed:Implementation Summary:1. CoreUserRequest DTO - Added role parsina from SCIM requests2. SCIM Constants - Added META ROLES and USER_PATCH_ATTR_ ROLES constants3. RoleAttr Mutator - Created mutator for handlina role assianments via SCIM PATCH operations4. ScimProvisioning - Updated to handle roles during user creation with proper validation5. ListenerRoleCannotHaveAdminOrManagerPermissionRule - Created validation rule to prevent listener role fromhaving admin/manager permissions6. CoreUser Response - Updated to include roles in SClM responses7. Unit Tests - Created comprehensive tests for the validation ruleKey Features:• Customers can now assign roles via SCIM (recorder, recorder & voice, analyst, listener, admin, manager)• Validation ensures listener role is onlv assianable if the LISTENER ROLE feature flaa is enabled•LIstener role cannot de comolned with aamin or manager permissions• Uses existing UpdateUserRolesAction for role syncing and logging• Follows platform validation rules (DependentRolesRule, ListenerRoleRequiresListenerFeatureRule)Next Step: Please contact Mario to update the customer that SCIM role management is now available for Teamtailorintearationposwtn chaten vapp/Component/SClM/ Constants.php +3app/Component/SCIM/ ® ScimProvisioning.php +85-15nse/ CoreUser.php +21ann/Comnonent/SCIM/Mutatore/Attributes/Ucer/M PoleAttr.nho 417ites/Userl ẞ RoleAttrTest.ohn +224* Reiect alliiAccent alliAsk anvthing 884-D)« Code SWF-1.6W Windsurf Teams 1:1 UTF-8io 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53490
|
1874
|
3
|
2026-05-18T12:10:43.192820+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106243192_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpSupport Daily - 5 m leftmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.com100% <78• Mon 18 May 15:10:42+•$18Nikolay Yankov (Presenting)EditHistoryTab# Proje( AtterSchel• Cursc* Ciauc|• Cost5app.oAllowoPiot8JimirZ (JY-2C UY-2Z [JY-27 [JY-28• Mon 18 May 15:10Z (JY-2https://fiminny.atlassian.net/browse/JY-20912• Sminny• Home| Salesforce M O 8 [ E Datadoa * Claude3 Circleci8 JiMINNY* For you© Recent |# Starred8. AppsQ SpacesStarred(9) Service-DeskJiminny (Old)Jiminny (New)I CID Platform TeamIID Enterprise Stability I...111 Processing Tearn(ID SE Kanban= More spaces= Filters(B DashboardsOperationsx Confiuence:: Teams% Customise sidebar0 Projects|E3 SSHA Sentry0 Tasks7 Insights & Coachin…0 DevDJ All BookmarkaSearch+ CreateAsk RovoCe, Add parent1 A Jy-20912We should implement the same fallback logic currently used for dialers - if the Salesforce admin token is expired or inactive, the system should search for another activeSalesforce token from any user within the same organisation and use it for CRM matching.Detailsstory point esumateAcceptance Criteria:• If the Salesforce admin token has expired, the system searches for another active Salesforce token within the organisation.• CRM object matching continues successfully using the fallback token.• Calls should not appear as "Unknown Customer" when another valid Salesforce connection exists in the organisation.Story PointsNoneOrganisationsNoneSubtasksAdd subtaskPriority= Medium'Linked work itemsAdd linked work itemFix versionsNone• ActivitySprintPlatform Sprint 5 Q2Work logDays1.5Add a comment.Suggest a reply…Who is working on this...?Status update…Need QAYesPto tos cretWoconCanny LinksOpen Canny LinksNikolay YankovMore fieldsBE: 1 dayQA: 0.5 day - Test onily Twillo disconnect flowParentNone20 5Nikolay YankovAneliya AngelovaNikolay IvanoLukas Kovalik3:10 PM | [Platform] Refinement ®...
|
NULL
|
2669527475592886929
|
NULL
|
visual_change
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpSupport Daily - 5 m leftmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.com100% <78• Mon 18 May 15:10:42+•$18Nikolay Yankov (Presenting)EditHistoryTab# Proje( AtterSchel• Cursc* Ciauc|• Cost5app.oAllowoPiot8JimirZ (JY-2C UY-2Z [JY-27 [JY-28• Mon 18 May 15:10Z (JY-2https://fiminny.atlassian.net/browse/JY-20912• Sminny• Home| Salesforce M O 8 [ E Datadoa * Claude3 Circleci8 JiMINNY* For you© Recent |# Starred8. AppsQ SpacesStarred(9) Service-DeskJiminny (Old)Jiminny (New)I CID Platform TeamIID Enterprise Stability I...111 Processing Tearn(ID SE Kanban= More spaces= Filters(B DashboardsOperationsx Confiuence:: Teams% Customise sidebar0 Projects|E3 SSHA Sentry0 Tasks7 Insights & Coachin…0 DevDJ All BookmarkaSearch+ CreateAsk RovoCe, Add parent1 A Jy-20912We should implement the same fallback logic currently used for dialers - if the Salesforce admin token is expired or inactive, the system should search for another activeSalesforce token from any user within the same organisation and use it for CRM matching.Detailsstory point esumateAcceptance Criteria:• If the Salesforce admin token has expired, the system searches for another active Salesforce token within the organisation.• CRM object matching continues successfully using the fallback token.• Calls should not appear as "Unknown Customer" when another valid Salesforce connection exists in the organisation.Story PointsNoneOrganisationsNoneSubtasksAdd subtaskPriority= Medium'Linked work itemsAdd linked work itemFix versionsNone• ActivitySprintPlatform Sprint 5 Q2Work logDays1.5Add a comment.Suggest a reply…Who is working on this...?Status update…Need QAYesPto tos cretWoconCanny LinksOpen Canny LinksNikolay YankovMore fieldsBE: 1 dayQA: 0.5 day - Test onily Twillo disconnect flowParentNone20 5Nikolay YankovAneliya AngelovaNikolay IvanoLukas Kovalik3:10 PM | [Platform] Refinement ®...
|
53488
|
NULL
|
NULL
|
NULL
|
|
53491
|
1874
|
4
|
2026-05-18T12:10:46.372541+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106246372_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5222591262487654398
|
-8636637129462003327
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpSupport Daily - 5 m leftmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.com+18Nikolay Yankov (Presenting)ehomtFileEditVewTabM Inbo7 PattF Proje• AterSche• Cursc* Ciau:|• Cоsя|@ app.o C Allov. 3 Pipe• SminnyC Projects |888 JiMINNY® For you© Recent# Starred8. AppsQ SpacesStarredS Service-DeskJiminny (Old)Jiminny (New) + --I 0D Platform TeamIID Enterprise Stabilty L..(ID SE Kanban= More spaces= FiitersCB DashboardsOperations* Confiuence:: Teams% Customise sidebarE3 SSH• Home| Salesforce @ O 88 [l El Datadoo @ # Ciaude3 CircleciA SentrySearchSpaces/LJinay (New) / 0 Jy-19309 / [J JY-20721Call Scoring filter for Exec reportsDescriptionNow that we have the call scoring feature, customers are asking for their report to be done only on calls with certain scores (either high or tow).|• Include the call scoring füter in the Exec Reports section in Kiosk• use the same dropdown structure that we have in OD• put it before Recipients• ensure the scores filter applied for the report whien fetching the calls for aanalisys |SubtasksLinked work itemsActivityWork logAodecomiiWho is working on this...status upoate.Pro tio: press M 50d2 tY-Z tY-2Z [JY-27 [JY-28 - Mon 18 May 15:10QJY-20J Tasks7 insights & Coachin0 DerDD Al BookmarkslCreateAsk RovoBacklog~** Improve StoryDetailsAssignee8 UnassignedAssign to meReporter2 Gelya DimitrovaP Quick start developmentLink this work item to your code byincluding keys when creating abranch, commit, or puli requestDrow, LEd wOsDismissDevelopment[ Open with VS Code!J Create branch* Create commit |ComponentsPlattormSub-ProductAdd optionsLabetsNone3:10 PM | [Platform] Refinement ®100% C8• Mon 18 May 15:10:465Nikolay YankolAneliya AngelovaNikolay IvanoLükas Kovalik...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53492
|
1874
|
5
|
2026-05-18T12:10:52.401596+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106252401_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4235983745889776938
|
-8204421443435123770
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpSupport Daily - 5 m leftmeet.google.com/cxs-eips-npt?authuser=lukas.kovalik%40jiminny.comNikolay Yankov (Presenting)+•$18ehomeFileEditViewtonetTabWndowM Inbol7 PlackF Proje( Atter( Schel© Cursc* Ciauc• Cos|5app.oAllowo Piothttps://jiminny.atlassian.net/browse/JY-20771• SminnyC Projects |888 JiMINNY* For you© Recent |# Starred8. AppsQ SpacesStarred9 Service-DeskJiminny (Old)Jiminny (New)ICD Platform Team(ID Enterprise Stability L...(ID SE Kanban= More spaces= Filters(B DashboardsOperationsx Confiuence: Teams% Customise sidebarE3 SSH• Home | Salesforce O 8 L E1 Datadog © % Ciaude3 CircleciA SentrySearchspaces /Jmicey ONew) / $ JY-19309 / [ JY-20771Call Scoring filter for Exec reports• Description|Now that we have the call scoring feature, customers are asking for their report to be done only on calls with certain scores (either high or low).|• Include the call scoring fiter in the Exec Reports section in Kiosk• use the same dropdown structure that we have in OD• put it before Recipients• ensure the scores filter applied for the report when fetching the calls for sanalisys |SubtasksLinked work itemsActivityWork logRodacomiterWho is working on thisStatus update...Pro tio: press M to col1 LY-2Z UY-2Z [Y-27 [JY-28 • Mon 18 May 15:10WJY-20 Tasks7 insights & Coachin.0 Dev|0J Al BookomarkaCreateAsk Rovo•1|Backdog~** Improve StoryDetailsAssignee& UnassignedAssign to meReporter2 Galya DimitrovaP Quick start developmentLink this work item to your code byIincluding keys when creating abranch, commit, or pull requestbelow. Learn moreDismissDevelopmentOpen with VS CodeJ Create branchCreate commit |ComponentsPlatformSub-ProductAdd optionsLabelsStory point esuim3:10 PM | [Platform] Refinement ®100% C8• Mon 18 May 15:10:525Nikolay YankolAneliya AngelovaNikolay IvanLukas Kovalik...
|
53491
|
NULL
|
NULL
|
NULL
|
|
53493
|
1874
|
6
|
2026-05-18T12:10:58.420467+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106258420_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8950623343946724334
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53494
|
1875
|
1
|
2026-05-18T12:11:15.056287+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106275056_m2.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
775695417232670985
|
5527291647994408855
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53495
|
1874
|
7
|
2026-05-18T12:11:28.667317+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106288667_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8950623343946724334
|
6686367685199443021
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
53493
|
NULL
|
NULL
|
NULL
|
|
53496
|
1874
|
8
|
2026-05-18T12:11:34.656649+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106294656_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5159095835385562987
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
53493
|
NULL
|
NULL
|
NULL
|
|
53497
|
1874
|
9
|
2026-05-18T12:11:40.739620+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106300739_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2240692385361527689
|
5529508263503171479
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
53498
|
1874
|
10
|
2026-05-18T12:11:43.769669+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-18/1779 /Users/lukas/.screenpipe/data/data/2026-05-18/1779106303769_m1.jpg...
|
PhpStorm
|
faVsco.js – ScimProvisioning.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>114 incoming commits<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\SCIM;\n\nuse Exception;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Component\\Acl\\RoleChangeContext;\nuse Jiminny\\Component\\Acl\\RoleChangeLogger;\nuse Jiminny\\Component\\Acl\\RoleChangeType;\nuse Jiminny\\Component\\SCIM\\Builders\\GroupFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Builders\\UsersFilterQueryBuilder;\nuse Jiminny\\Component\\SCIM\\Mutators\\GroupPatchOperation;\nuse Jiminny\\Component\\SCIM\\Mutators\\UserPatchOperation;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreGroupRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\CoreUserRequest;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetGroupByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\GetUserByQuery;\nuse Jiminny\\DTO\\SCIM\\AAD\\Request\\PatchGroup;\nuse Jiminny\\Events\\Users\\UserCreated;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\JobTitle;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Services\\UserService;\nuse Jiminny\\Contracts\\Acl\\RoleRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Jiminny\\Rules\\DependentRolesRule;\nuse Jiminny\\Rules\\ListenerRoleCannotHaveAdminOrManagerPermissionRule;\nuse Jiminny\\Rules\\ListenerRoleRequiresListenerFeatureRule;\nuse Jiminny\\Actions\\UpdateUserRolesAction;\nuse Jiminny\\DTO\\Roles\\UserRolesSyncDTO;\nuse Sentry;\n\nclass ScimProvisioning\n{\n public function __construct(\n private readonly Dispatcher $eventDispatcher,\n private readonly UserService $userService,\n private readonly RoleChangeLogger $roleChangeLogger,\n private readonly RoleRepositoryInterface $roleRepository,\n private readonly UpdateUserRolesAction $updateUserRolesAction,\n ) {\n }\n\n public function validateUserIdInput($id, Team $team): bool\n {\n if (! User::isUuid4($id)) {\n return false;\n }\n $user = $this->getUserById($id);\n\n return $user instanceof User && $team->isSame($user->getTeam());\n }\n\n public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User\n {\n $actions = [];\n if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_FIRST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getFirstName(),\n );\n }\n if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_LAST_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getLastName(),\n );\n }\n if ((! $user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [true, 'True', 1],\n true,\n )) ||\n ($user->isStatusActive() && in_array(\n array_get(\n $dto->getRawRequest(),\n Constants::USER_PATCH_ATTR_ACTIVE,\n ),\n [false, 'False', 0],\n true,\n ))\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_ACTIVE,\n Constants::META_OPERATIONS_REPLACE,\n $user->getStatus() === 1 ? 0 : 1,\n );\n }\n if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||\n (! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())\n ) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_TITLE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getTitle(),\n );\n }\n if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailPrimaryWork(),\n );\n }\n if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getEmailOther(),\n );\n }\n if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getPrimaryPhoneNumber() ?? '',\n );\n }\n if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {\n $actions[] = $this->returnAction(\n Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getSecondaryPhoneNumber() ?? '',\n );\n }\n // no username update support. We rely on email=username in general\n\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n /** @return array{path: string, op: string, value: mixed} */\n private function returnAction(string $path, string $op, mixed $value): array\n {\n return [\n Constants::META_PATH => $path,\n Constants::META_OP => $op,\n Constants::META_VALUE => $value,\n ];\n }\n\n public function getUserById(string $id): ?User\n {\n return User::uuid($id, false)->first();\n }\n\n public function getGroupById(string $id): ?Group\n {\n return Group::uuid($id, false)->first();\n }\n\n public function validateGroupIdInput(string $id, Team $team): bool\n {\n if (! Group::isUuid4($id)) {\n return false;\n }\n\n try {\n /** @var Group|null $group */\n $group = Group::uuid($id);\n } catch (Exception) {\n return false;\n }\n\n return $group instanceof Group && $team->isSame($group->getTeam());\n }\n\n public function patchUserOperation(array $actions, User $user): User\n {\n /**\n * Supported operations\n * on emails, phones, name, title, status except remove primaryEmail\n */\n foreach ($actions as $action) {\n $user = (new UserPatchOperation($user, $action))->doUpdate();\n }\n\n return $user;\n }\n\n public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder\n {\n $query = Group::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new GroupFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool\n {\n /**\n * Supported operations\n * - replace group name\n * - add user member of the group\n */\n foreach ($dto->getActions() as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return true;\n }\n\n public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder\n {\n $query = User::query()\n ->where('team_id', $team->getId());\n\n foreach ($dto->getFilters() as $filter) {\n (new UsersFilterQueryBuilder($filter))->addToQuery($query);\n }\n\n return $query;\n }\n\n public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User\n {\n $phone = $dto->getPrimaryPhoneNumber();\n $secondaryPhone = $dto->getSecondaryPhoneNumber();\n\n if (! $this->isValidPhone($phone, $team->country_code)) {\n $phone = null;\n }\n\n if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {\n $secondaryPhone = null;\n }\n\n $isActive = $dto->getActive();\n\n $userUpdateData = [\n 'name' => $dto->getName(),\n 'secondary_email' => $dto->getEmailOther(),\n 'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,\n 'language' => $team->default_language,\n 'timezone' => $team->default_timezone,\n 'country_code' => $team->country_code,\n 'conference_slug' => $this->userService->generateSlug($dto->getName()),\n ];\n\n // Do not change phone if it is not provided\n if ($phone !== null) {\n $userUpdateData['phone'] = $phone;\n }\n\n // Do not change secondary phone if it is not provided\n if ($secondaryPhone !== null) {\n $userUpdateData['secondary_phone'] = $secondaryPhone;\n }\n\n try {\n /** @var User $newUser */\n $newUser = $team\n ->users()\n ->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])\n ->updateOrCreate(\n ['email' => $dto->getEmailPrimaryWork()],\n $userUpdateData,\n );\n\n $this->assignRolesFromScim($newUser, $dto, $team);\n\n if (! empty($dto->getTitle())) {\n $jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();\n if ($jobTitle instanceof JobTitle) {\n $newUser->update(['job_title_id' => $jobTitle->getId()]);\n } else {\n /** @var JobTitle $newJobTitle */\n $newJobTitle = $team->jobs()->create([\n 'name' => $dto->getTitle(),\n 'is_selectable' => 0,\n ]);\n $newUser->update(['job_title_id' => $newJobTitle->getId()]);\n }\n }\n\n if ($newUser->wasRecentlyCreated) {\n $this->eventDispatcher->dispatch(new UserCreated($newUser));\n }\n\n return $newUser;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n private function isValidPhone(?string $number, string $countryCode): bool\n {\n if ($number === null) {\n return true;\n }\n\n $validator = Validator::make(\n ['phone' => $number],\n ['phone' => ['phone:INTERNATIONAL,' . $countryCode]]\n );\n\n return ! $validator->fails();\n }\n\n private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void\n {\n $requestedRoles = $dto->getRoles();\n\n if (empty($requestedRoles)) {\n if (! $user->roles()->exists()) {\n $user->addRole(User::ROLE_ANALYST);\n /** @var Role $role */\n $role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();\n\n $this->roleChangeLogger->log(\n activeUser: null,\n affected: $user,\n role: $role,\n type: $user->wasRecentlyCreated\n ? RoleChangeType::CREATE_USER\n : RoleChangeType::ADD_ROLE,\n context: RoleChangeContext::SCIM,\n );\n }\n\n return;\n }\n\n $visibleRoles = $this->roleRepository->findAllByTeam($team->getId());\n\n $roleIds = [];\n foreach ($requestedRoles as $roleName) {\n $role = $visibleRoles->firstWhere('name', $roleName);\n\n if ($role === null) {\n continue;\n }\n\n $roleIds[] = $role->getId();\n }\n\n if (empty($roleIds)) {\n return;\n }\n\n $validator = Validator::make(\n ['roles' => $roleIds],\n [\n 'roles' => [\n 'required',\n 'array',\n 'min:1',\n new DependentRolesRule($visibleRoles),\n new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),\n ],\n 'roles.*' => [\n 'required',\n 'distinct',\n 'in:' . $visibleRoles->pluck('id')->implode(','),\n new ListenerRoleRequiresListenerFeatureRule($team),\n ],\n ]\n );\n\n if ($validator->fails()) {\n return;\n }\n\n $roles = $visibleRoles->whereIn('id', $roleIds);\n\n $dto = new UserRolesSyncDTO(\n user: $user,\n activeUser: null,\n roles: $roles,\n );\n\n $this->updateUserRolesAction->execute($dto);\n }\n\n public function deleteGroup($group): bool\n {\n $users = $group->members()->get();\n\n foreach ($users as $user) {\n $user->update(['group_id' => null]);\n }\n\n return $group->delete();\n }\n\n public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group\n {\n try {\n /** @var Group|null $existingGroup */\n $existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();\n\n if ($existingGroup) {\n if ($existingGroup->getAttribute('deleted_at')) {\n $existingGroup->restore();\n }\n\n return $existingGroup;\n }\n\n /** @var Group $newGroup */\n $newGroup = $team->groups()->updateOrCreate(\n ['name' => $dto->getDisplayName()],\n [\n 'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),\n 'user_id' => $team->getOwner()->getId(),\n 'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),\n 'default_timezone' => $team->getDefaultTimezone(),\n 'default_language' => $team->getDefaultLanguage(),\n 'country_code' => $team->getCountryCode(),\n 'playbook_id' => $team->getDefaultPlaybookId(),\n ],\n );\n\n return $newGroup;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n return null;\n }\n }\n\n public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group\n {\n $actions = [];\n\n if ($group->getName() !== $dto->getDisplayName()) {\n $actions[] = $this->returnAction(\n Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,\n Constants::META_OPERATIONS_REPLACE,\n $dto->getDisplayName(),\n );\n }\n\n foreach ($actions as $action) {\n $group = (new GroupPatchOperation($group, $action))->doUpdate();\n }\n\n return $group;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny_jupiter","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE id = 1;\n\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;\nSELECT * FROM crm_fields WHERE id = 2234;\nSELECT * FROM crm_field_values WHERE crm_field_id = 2234;\n\nselect * from crm_profiles where user_id = 143;\n\nselect * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO\nselect * from business_processes where crm_configuration_id = 39;\n# 01941000000H669AAC, 01941000000H66JAAS\n\nselect * from record_type_field_values\n where record_type_id IN (24);\n\nselect * from crm_field_values where id IN (2730);\n\nselect * from crm_configurations where id = 39;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce'; #1035\n\n\nselect * from users where team_id = 1; # 222 group 3\nSELECT * FROM activities WHERE user_id = 222 order by id desc;\nselect * from sidekick_settings where team_id = 1;\nselect * from teams where id = 1;\nselect * from team_features where team_id = 1;\n\nselect * from activities where crm_configuration_id = 2\nand provider = 'ms-teams' and id = 608765;\n\nSELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';\n\nselect * from sidekick_settings where team_id = 2;\n\nSELECT * FROM activities WHERE id = 608660;\nselect * from activity_summary_logs where activity_id = 608660;\nselect * from ai_prompts where transcription_id = 11214;\n\n# ********************************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;\n# id: 608818, crm: 59628809737\nSELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;\n# id: 608821, crm: 59632069252\nSELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,\nplaybook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,\nscheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at\nFROM activities a\njoin calendar_events ce on a.calendar_event_id = ce.id\nWHERE a.id IN (608818, 608821);\n\nselect * from users where team_id = 1;\nselect * from team_settings where team_id = 1;\nselect * from crm_profiles where crm_configuration_id = 39 order by user_id;\n\nselect * from team_features where team_id = 1;\n\nselect * from users where team_id = 2;\n\nSELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639\n# Preslava N. Ivanova, grou id 3\n\nSELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;\n\nselect * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';\n\nselect\n a.id,\n a.type,\n a.scheduled_start_time,\n a.actual_start_time,\n a.created_at,\n a.opportunity_id,\n a.status\nFROM activities a\nWHERE opportunity_id = 344\nand status IN ('completed', 'received', 'delivered')\nand (\n (a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')\nOR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))\n;\n\nSELECT * FROM users WHERE id = 222;\n\nSELECT * FROM crm_profiles WHERE user_id = 222;\nselect * from crm_layouts where crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;\n\nselect * from group_deal_risk_types;\n\nselect * from opportunities where team_id = 1;\n\nSELECT * FROM opportunities WHERE id = 315;\nSELECT * FROM crm_field_data WHERE object_id = 315;\nselect * from crm_field_data where object_id = 260;\n\nselect * from generic_ai_prompts where subject_id = 315;\n\nselect * from teams; # 36, 21, 121, james.graham@bullhorn.jiminny.com\nSELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';\n\n# ************************************************************************************\nselect * from teams where id = 1;\nselect * from crm_configurations where id = 39;\nselect * from users where team_id = 1;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 1;\n# 1 - 00541000004281rAAA\n# 204 - 0052g000003freeAAA\n# 429 - 0052g000003qGOiAAM\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\nselect * from activities where type = 'softphone'\nand created_at > '2024-12-11 15:24:36' order by id desc;\n\nselect * from activity_providers where team_id = 1;\nselect * from activity_provider_users where activity_provider_id = 328;\n\nselect * from opportunities where crm_configuration_id = 39\nAND account_id = 178 AND is_closed = false\norder by created_at DESC;\n\nselect * from contacts where id = 3952;\nselect * from accounts where id = 178;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations where id = 21;\nselect * from users where team_id = 36;\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 36;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 36\nand sa.provider = 'bullhorn';\n\nselect * from social_accounts where id = 348;\nUPDATE social_accounts SET\nprovider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',\nprovider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',\nexpires = 1733998131,\nstate = 'connected'\nWHERE id = 348;\n\n# ************************************************************************************\nselect * from teams where id = 31;\nselect * from crm_configurations where id = 18;\n\nselect * from users where team_id = 31; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 31;\n\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 31\nand sa.provider = 'close';\n\nselect * from contacts where crm_configuration_id = 18;\n\n# ********************** NEPTUNE **************************************************************\nselect * from teams;\nselect * from users where id IN (1030, 1035, 1052);\nselect * from crm_configurations;\n\nselect * from users where team_id = 65; # 257\nselect * from team_settings where team_id = 65; # 257\nselect * from invitations where team_id = 65; # 257\nselect * from users where email = 'integration-account@jiminny.com'; # 257\nselect u.email, cp.* from users u\njoin crm_profiles cp on u.id = cp.user_id\nwhere u.team_id = 65;\n\nselect * from crm_configurations where id = 53;\nselect * from accounts where crm_configuration_id = 53 order by id desc;\nselect * from leads where crm_configuration_id = 53 order by id desc;\nselect * from contacts where crm_configuration_id = 53 order by id desc;\nselect * from opportunities where crm_configuration_id = 53 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 53 order by id desc;\nselect * from crm_fields where crm_configuration_id = 53 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 53 order by id desc;\nselect * from stages where crm_configuration_id = 53 order by id desc;\n\n\nselect * from crm_profiles where crm_configuration_id = 13;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\nand sa.provider = 'integration-app';\n\nselect * from contacts where crm_configuration_id = 13;\n\nselect * from social_accounts where sociable_id = 283;\n\nSELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';\n\nselect * from activity_providers where team_id = 65;\nSELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 65\n;\n\n# ***************************** STAGING ********************************************\nSELECT * FROM teams;\nSELECT * FROM teams WHERE id = 88;\nSELECT * FROM teams WHERE id = 89;\nselect * from team_settings where team_id = 89;\nSELECT * FROM users WHERE team_id = 89;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 89;\n\nselect * from users;\nSELECT * FROM social_accounts WHERE sociable_id = 1761;\nSELECT * FROM crm_configurations WHERE id = 70;\nselect * from accounts where crm_configuration_id = 70 order by id desc;\nselect * from leads where crm_configuration_id = 70 order by id desc;\nselect * from contacts where crm_configuration_id = 70 order by id desc;\nselect * from opportunities where crm_configuration_id = 70 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 70 order by id desc;\nselect * from crm_fields where crm_configuration_id = 70 order by id desc;\nselect * from crm_field_values where crm_field_id = 3536 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 70 order by id desc;\nselect * from stages where crm_configuration_id = 70 order by id desc;\nselect * from business_processes where crm_configuration_id = 70 order by id desc;\nselect * from business_process_stages where business_process_id = 34;\n\nselect * from contacts where id = 10468;\n\nselect * from crm_layouts where crm_configuration_id = 70;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;\nSELECT * FROM crm_fields WHERE id IN (3533,3534,3535);\n\nselect * from activities where crm_configuration_id = 70\nand (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;\n\nSELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;\nSELECT * FROM activities where crm_configuration_id = 69 ;\n\nSELECT * FROM users WHERE email LIKE '%jiminny_web_sa2@jiminny.com%';\nSELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;\nSELECT * FROM opportunities WHERE id = 385;\n\nselect * from participants p\njoin activities a on p.activity_id = a.id\nwhere a.crm_configuration_id = 70\nand (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);\nSELECT * FROM participants WHERE id = 1013638;\n\nselect * from teams where id = 90;\nselect * from users where team_id = 90;\nselect * from social_accounts where social_accounts.sociable_id IN (1960,1760);\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 71;\nselect * from invitations where team_id = 90;\n\nselect * from crm_configurations where id = 71;\nselect * from accounts where crm_configuration_id = 71 order by id desc;\nselect * from leads where crm_configuration_id = 71 order by id desc;\nselect * from contacts where crm_configuration_id = 71 order by id desc;\nselect * from opportunities where crm_configuration_id = 71 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 71 order by id desc;\nselect * from crm_fields where crm_configuration_id = 71 order by id desc;\nselect * from crm_field_values where crm_field_id = 3341 order by id desc;\nselect * from crm_layouts where crm_configuration_id = 71 order by id desc;\nselect * from stages where crm_configuration_id = 71 order by id desc;\n\nselect * from users order by secondary_email desc;\nselect u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa\n join users u on sa.sociable_id = u.id\nwhere sa.provider = 'google' and u.email LIKE 'aneliya%';\n\nselect * from failed_jobs order by id desc;\n\nselect * from users where email = 'ben.allwright@learningpeople.co.uk' or secondary_email = 'ben.allwright@learningpeople.co.uk';\n\nselect * from teams;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 39;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 1\nand sa.provider = 'salesforce';\n\n# ************************************************************************************\nSELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;\nSELECT * FROM crm_configurations WHERE id = 70;\n\nselect * from teams where id = 1;\nselect * from groups where team_id = 1;\nselect * from users where team_id = 1;\n\nselect o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o\njoin users u on o.user_id = u.id\njoin groups g on u.group_id = g.id\njoin role_user ru on u.id = ru.user_id\njoin roles r on ru.role_id = r.id\nwhere o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';\n\nselect * from role_user where user_id = 143;\nselect * from roles;\n\nselect * from role_user;\nselect * from groups where id = 9;\nselect * from scope_groups where group_id = 9;\n\n# ************************************************************************************\nselect * from teams where id = 36;\nselect * from crm_configurations;\nSELECT * FROM social_accounts WHERE sociable_id = 121;\n\nhttps://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105\nhttps://crmsandbox.zoho.com/crm/\n\nhttps://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080\n https://crm.zoho.com/crm/\n org3469620\n\nSELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;\n\nselect * from users where email LIKE \"%mobile_automation_%\";\nselect * from social_accounts where sociable_id IN (2228);\nselect * from crm_profiles where user_id IN (2222,2223,2226,2227);\n\nselect * from teams order by id desc;\nSELECT * FROM users WHERE id = 2229;\nSELECT * FROM crm_profiles WHERE user_id = 2229;\nselect * from opportunities where crm_configuration_id = 88;\nselect * from crm_fields where crm_configuration_id = 88;\nselect * from crm_profiles where crm_configuration_id = 88;\n\nSELECT * FROM teams WHERE id = 1;\n\nSELECT * FROM users WHERE id = 143;\nSELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;\n\nhttps://app.staging.jiminny.com/ondemand?\n min_duration=1\n &\n only_recorded=1\n &\n user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e\n &\n sequence_number=2\n\n select * from users where team_id = 1 and email like '%stoyan%'\n\nselect * from coaching_feedbacks;\n\nselect * from teams;\nSELECT * FROM users WHERE team_id = 36;\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from users where id = 143;\n\nSELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\nSELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;\n\nselect * from users where team_id = 2;\nselect * from activities where crm_configuration_id = 39\nand activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'\nAND user_id = 143\norder by id desc;\n\n# ************************************************************************************\nselect * from teams where id = 142; # 2312, 126\nselect * from team_settings;\nselect * from users where team_id = 142; # 21642\nSELECT * FROM social_accounts WHERE sociable_id = 21642;\nSELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;\nselect * from crm_profiles where id IN (93);\nselect * from invitations;\nselect * from team_features where team_id = 1;\n\nSELECT * FROM crm_configurations WHERE id = 126;\nselect * from accounts where crm_configuration_id = 126 order by id desc;\nselect * from leads where crm_configuration_id = 126 order by id desc;\nselect * from contacts where crm_configuration_id = 126 order by id desc;\nselect * from opportunities where crm_configuration_id = 126 order by id desc;\nselect * from crm_profiles where crm_configuration_id = 126 order by id desc;\nselect * from crm_fields where crm_configuration_id = 126 # 11060\n# and type IN ('picklist', 'status')\n# and object_type = 'task'\norder by id desc;\n# 5731,5732,5733\nselect DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;\nselect * from crm_layouts where crm_configuration_id = 126 order by id desc;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);\nselect * from stages where crm_configuration_id = 126 order by id desc;\nselect * from business_processes where crm_configuration_id = 126 order by id desc;\nselect * from business_process_stages where business_process_id IN (76,75,74,73);\nselect * from playbooks where team_id = 142;\nselect * from playbook_layouts where playbook_id IN (108);\nSELECT * FROM playbook_categories WHERE playbook_id IN (108);\n\nselect * from teams where id = 130;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 2\nand sa.provider = 'hubspot';\n\nSELECT * FROM activities\n WHERE crm_configuration_id = 110;\n\nselect * from teams;\nselect * from crm_configurations;\n\nSELECT * FROM activities WHERE id = 628773;\nSELECT * FROM crm_profiles WHERE user_id = 1460;\nSELECT * FROM social_accounts WHERE sociable_id = 2291;\n\nselect * from teams;\nselect ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id\njoin permission_role pr on pr.role_id = ru.role_id\n join permissions p on p.id = pr.permission_id\nwhere team_id = 495 and p.name IN ('dial');\n\nselect * from teams where id = 145;\nselect * from crm_configurations where id = 129;\nselect * from social_accounts where sociable_id = 2317;\nSELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;\n\nselect * from teams where id = 1;\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 39;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;\nSELECT * FROM crm_layout_entities WHERE id = 5507;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');\n\nselect * from teams;\nselect * from activities where crm_configuration_id = 14;\n\nSELECT * FROM social_accounts where provider = 'copper';\n\nselect * from activities where id = 628467;\nselect * from participants where activity_id = 628467;\n\nSELECT * FROM contacts WHERE id = 3969;\nSELECT * FROM accounts WHERE id = 177;\n\nSELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;\n\n# ********************* BH\nselect * from teams where id = 36;\nSELECT * FROM crm_configurations WHERE id = 21;\nselect * from activities where crm_configuration_id = 21 and id = 607901;\nselect * from activities where crm_configuration_id = 21;\n\nselect * roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 226;\n\nselect * from migrations order by id desc;\n\n# mercury\n# neptune\n# earth\n\nselect * from teams;\nselect * from teams where id = 19;\nselect * from teams where id = 27;\nselect * from users where team_id = 27;\nSELECT * FROM crm_configurations WHERE id = 42;\n\nselect * from social_accounts sa\njoin users u on sa.sociable_id = u.id\nwhere u.team_id = 19\nand sa.provider = 'pipedrive';\n\nselect * from activities where id = 631461;\nSELECT * FROM crm_field_values WHERE crm_field_id = 180;\n\nselect * from teams where id = 2;\nSELECT * FROM social_accounts WHERE sociable_id = 89;\n\nSELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273\nselect * from activity_summary_logs where activity_id = 634273;\n\nselect * from sidekick_settings where team_id = 2;\n\nselect * from teams; # 2, 2\nSELECT * FROM crm_configurations WHERE team_id = 2; # 2\nselect * from team_features where team_id = 2;\nselect * from features;\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';\nSELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;\n\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from users where team_id = 1 and id IN (7160, 3248);\nselect * from migrations order by id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nselect * from teams where id = 1;\nselect * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;\nselect * from groups where id = 565;\nselect * from playbooks where team_id = 1;\nselect * from playbooks where id = 175;\nselect * from playbook_categories where playbook_id = 175;\nselect * from users where team_id = 1052;\nselect * from users where id = 7160;\nselect * from crm_profiles where user_id = 7160;\nselect * from features;\nselect\n *\n# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,\n# crm_configuration_id, crm_provider_id, transcription_id, status\nfrom activities where crm_configuration_id = 1 and type = 'conference'\n# and crm_provider_id IS NOT NULL\nand provider != 'uploader' and actual_start_time IS NOT NULL\nORDER by id desc;\nselect * from activities where id = 54747783; # 00UO400000pCzojMAC\n\nselect p.id, p.activity_type, pc.id, pc.name\nFROM playbooks p\njoin playbook_categories pc on p.id = pc.playbook_id\nwhere p.team_id = 1 and p.activity_type = 'event';\n\nSELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';\nSELECT * FROM crm_field_values WHERE crm_field_id = 4;\n\nselect * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id\nwhere crm_configuration_id = 1 and pl.playbook_id = 175;\n\nselect * from teams;\nSELECT r.* FROM automated_reports r\njoin teams t on r.team_id = t.id\nWHERE r.frequency = 'daily'\n and r.status = 1\nAND t.status = 'active'\nAND (r.expires_at >= now() OR r.expires_at IS NULL);\n\nselect * from automated_report_results where report_id IN (18, 33);\n\nselect * from users where team_id = 1 and id = 1047;\nSELECT * FROM social_accounts WHERE sociable_id = 1047;\n\nselect * from activity_searches where id = 10932;\nselect * from activity_search_filters where activity_search_id = 10932;\nselect * from automated_reports order by id desc;\nselect * from automated_report_results order by id desc;\nselect * from automated_reports where id IN (55);\nselect * from automated_report_results where id IN (81);\nselect * from users where id IN (10633, 13987, 11985);\nselect * from users where group_id IN (3710);\n\nSELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;\n\nselect * from teams;\nselect * from accounts where team_id = 1;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2;\nSELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;\n\nselect * from teams where id = 1029;\nselect * from crm_configurations where provider = 'pipedrive';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1029 and sa.provider = 'pipedrive';\n\n[\n {\n \"user_id\": \"23460 (owner)\",\n \"email\": \"integration-account@pipedrive.jiminny.com\",\n \"id\": 69,\n \"sociable_id\": 23460,\n \"provider_user_id\": \"19555731\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA\",\n \"provider_refresh_token\": \"5034113:19555731:87c14258f0c813d02767ee975f6044d46b6b2bfc\",\n \"expires\": 1779091997,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"connected\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 08:23:28\",\n \"updated_at\": \"2026-05-18 07:13:18\",\n \"provider_user_token_encrypted\": \"eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n },\n {\n \"user_id\": \"23463\",\n \"email\": \"jiminny_web_sa@pipedrive.jiminny.com\",\n \"id\": 72,\n \"sociable_id\": 23463,\n \"provider_user_id\": \"23270841\",\n \"provider_user_token\": \"v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU\",\n \"provider_refresh_token\": \"5034113:23270841:34790b44838f5fd422c2d2c82e00f1ecf2178ad1\",\n \"expires\": 1753837219,\n \"refresh_token_expires\": null,\n \"provider\": \"pipedrive\",\n \"state\": \"full-refresh\",\n \"auth_scope\": \"base,deals:full,activities:full,contacts:full,search:read\",\n \"retry_after\": null,\n \"created_at\": \"2025-04-16 10:41:12\",\n \"updated_at\": \"2025-07-30 01:00:17\",\n \"provider_user_token_encrypted\": \"eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=\",\n \"provider_refresh_token_encrypted\": \"eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==\",\n \"encryption_key\": \"0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91\",\n \"sociable_type\": \"user\",\n \"owner_id\": 23460\n }\n]","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8950623343946724334
|
6686367685199443021
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\SCIM;
use Exception;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Jiminny\Component\Acl\RoleChangeContext;
use Jiminny\Component\Acl\RoleChangeLogger;
use Jiminny\Component\Acl\RoleChangeType;
use Jiminny\Component\SCIM\Builders\GroupFilterQueryBuilder;
use Jiminny\Component\SCIM\Builders\UsersFilterQueryBuilder;
use Jiminny\Component\SCIM\Mutators\GroupPatchOperation;
use Jiminny\Component\SCIM\Mutators\UserPatchOperation;
use Jiminny\DTO\SCIM\AAD\Request\CoreGroupRequest;
use Jiminny\DTO\SCIM\AAD\Request\CoreUserRequest;
use Jiminny\DTO\SCIM\AAD\Request\GetGroupByQuery;
use Jiminny\DTO\SCIM\AAD\Request\GetUserByQuery;
use Jiminny\DTO\SCIM\AAD\Request\PatchGroup;
use Jiminny\Events\Users\UserCreated;
use Jiminny\Models\Group;
use Jiminny\Models\JobTitle;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\UserService;
use Jiminny\Contracts\Acl\RoleRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Jiminny\Rules\DependentRolesRule;
use Jiminny\Rules\ListenerRoleCannotHaveAdminOrManagerPermissionRule;
use Jiminny\Rules\ListenerRoleRequiresListenerFeatureRule;
use Jiminny\Actions\UpdateUserRolesAction;
use Jiminny\DTO\Roles\UserRolesSyncDTO;
use Sentry;
class ScimProvisioning
{
public function __construct(
private readonly Dispatcher $eventDispatcher,
private readonly UserService $userService,
private readonly RoleChangeLogger $roleChangeLogger,
private readonly RoleRepositoryInterface $roleRepository,
private readonly UpdateUserRolesAction $updateUserRolesAction,
) {
}
public function validateUserIdInput($id, Team $team): bool
{
if (! User::isUuid4($id)) {
return false;
}
$user = $this->getUserById($id);
return $user instanceof User && $team->isSame($user->getTeam());
}
public function updateUserAttributesIfChanged(User $user, CoreUserRequest $dto, Team $team): User
{
$actions = [];
if (! str_starts_with($user->getName(), $dto->getFirstName() . ' ')) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_FIRST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getFirstName(),
);
}
if (! str_contains($user->getName(), ' ' . $dto->getLastName())) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_LAST_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getLastName(),
);
}
if ((! $user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[true, 'True', 1],
true,
)) ||
($user->isStatusActive() && in_array(
array_get(
$dto->getRawRequest(),
Constants::USER_PATCH_ATTR_ACTIVE,
),
[false, 'False', 0],
true,
))
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_ACTIVE,
Constants::META_OPERATIONS_REPLACE,
$user->getStatus() === 1 ? 0 : 1,
);
}
if ((! $user->job()->exists() && ! in_array($dto->getTitle(), ['', null])) ||
(! in_array($dto->getTitle(), ['', null]) && $user->getJobTitle()->name !== $dto->getTitle())
) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_TITLE,
Constants::META_OPERATIONS_REPLACE,
$dto->getTitle(),
);
}
if ($user->getEmailAddress() !== $dto->getEmailPrimaryWork()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PRIMARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailPrimaryWork(),
);
}
if ($user->getSecondaryEmailAddress() !== $dto->getEmailOther()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_SECONDARY_EMAIL,
Constants::META_OPERATIONS_REPLACE,
$dto->getEmailOther(),
);
}
if ($user->getAttribute('phone') !== $dto->getPrimaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER,
Constants::META_OPERATIONS_REPLACE,
$dto->getPrimaryPhoneNumber() ?? '',
);
}
if ($user->getAttribute('secondary_phone') !== $dto->getSecondaryPhoneNumber()) {
$actions[] = $this->returnAction(
Constants::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE,
Constants::META_OPERATIONS_REPLACE,
$dto->getSecondaryPhoneNumber() ?? '',
);
}
// no username update support. We rely on email=username in general
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
/** @return array{path: string, op: string, value: mixed} */
private function returnAction(string $path, string $op, mixed $value): array
{
return [
Constants::META_PATH => $path,
Constants::META_OP => $op,
Constants::META_VALUE => $value,
];
}
public function getUserById(string $id): ?User
{
return User::uuid($id, false)->first();
}
public function getGroupById(string $id): ?Group
{
return Group::uuid($id, false)->first();
}
public function validateGroupIdInput(string $id, Team $team): bool
{
if (! Group::isUuid4($id)) {
return false;
}
try {
/** @var Group|null $group */
$group = Group::uuid($id);
} catch (Exception) {
return false;
}
return $group instanceof Group && $team->isSame($group->getTeam());
}
public function patchUserOperation(array $actions, User $user): User
{
/**
* Supported operations
* on emails, phones, name, title, status except remove primaryEmail
*/
foreach ($actions as $action) {
$user = (new UserPatchOperation($user, $action))->doUpdate();
}
return $user;
}
public function translateQueryStringsToGroupModelQuery(GetGroupByQuery $dto, Team $team): Builder
{
$query = Group::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new GroupFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function patchGroupOperation(PatchGroup $dto, Team $team, Group $group): bool
{
/**
* Supported operations
* - replace group name
* - add user member of the group
*/
foreach ($dto->getActions() as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return true;
}
public function translateQueryStringsToUserModelQuery(GetUserByQuery $dto, Team $team): Builder
{
$query = User::query()
->where('team_id', $team->getId());
foreach ($dto->getFilters() as $filter) {
(new UsersFilterQueryBuilder($filter))->addToQuery($query);
}
return $query;
}
public function createOrUpdateNewUser(CoreUserRequest $dto, Team $team): ?User
{
$phone = $dto->getPrimaryPhoneNumber();
$secondaryPhone = $dto->getSecondaryPhoneNumber();
if (! $this->isValidPhone($phone, $team->country_code)) {
$phone = null;
}
if (! $this->isValidPhone($secondaryPhone, $team->country_code)) {
$secondaryPhone = null;
}
$isActive = $dto->getActive();
$userUpdateData = [
'name' => $dto->getName(),
'secondary_email' => $dto->getEmailOther(),
'status' => $isActive ? User::STATUS_ACTIVE : User::STATUS_DEACTIVATED,
'language' => $team->default_language,
'timezone' => $team->default_timezone,
'country_code' => $team->country_code,
'conference_slug' => $this->userService->generateSlug($dto->getName()),
];
// Do not change phone if it is not provided
if ($phone !== null) {
$userUpdateData['phone'] = $phone;
}
// Do not change secondary phone if it is not provided
if ($secondaryPhone !== null) {
$userUpdateData['secondary_phone'] = $secondaryPhone;
}
try {
/** @var User $newUser */
$newUser = $team
->users()
->whereIn('users.status', [User::STATUS_ACTIVE, User::STATUS_DEACTIVATED])
->updateOrCreate(
['email' => $dto->getEmailPrimaryWork()],
$userUpdateData,
);
$this->assignRolesFromScim($newUser, $dto, $team);
if (! empty($dto->getTitle())) {
$jobTitle = $team->jobs()->where('name', $dto->getTitle())->first();
if ($jobTitle instanceof JobTitle) {
$newUser->update(['job_title_id' => $jobTitle->getId()]);
} else {
/** @var JobTitle $newJobTitle */
$newJobTitle = $team->jobs()->create([
'name' => $dto->getTitle(),
'is_selectable' => 0,
]);
$newUser->update(['job_title_id' => $newJobTitle->getId()]);
}
}
if ($newUser->wasRecentlyCreated) {
$this->eventDispatcher->dispatch(new UserCreated($newUser));
}
return $newUser;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
private function isValidPhone(?string $number, string $countryCode): bool
{
if ($number === null) {
return true;
}
$validator = Validator::make(
['phone' => $number],
['phone' => ['phone:INTERNATIONAL,' . $countryCode]]
);
return ! $validator->fails();
}
private function assignRolesFromScim(User $user, CoreUserRequest $dto, Team $team): void
{
$requestedRoles = $dto->getRoles();
if (empty($requestedRoles)) {
if (! $user->roles()->exists()) {
$user->addRole(User::ROLE_ANALYST);
/** @var Role $role */
$role = Role::query()->where(['name' => User::ROLE_ANALYST])->firstOrFail();
$this->roleChangeLogger->log(
activeUser: null,
affected: $user,
role: $role,
type: $user->wasRecentlyCreated
? RoleChangeType::CREATE_USER
: RoleChangeType::ADD_ROLE,
context: RoleChangeContext::SCIM,
);
}
return;
}
$visibleRoles = $this->roleRepository->findAllByTeam($team->getId());
$roleIds = [];
foreach ($requestedRoles as $roleName) {
$role = $visibleRoles->firstWhere('name', $roleName);
if ($role === null) {
continue;
}
$roleIds[] = $role->getId();
}
if (empty($roleIds)) {
return;
}
$validator = Validator::make(
['roles' => $roleIds],
[
'roles' => [
'required',
'array',
'min:1',
new DependentRolesRule($visibleRoles),
new ListenerRoleCannotHaveAdminOrManagerPermissionRule($visibleRoles),
],
'roles.*' => [
'required',
'distinct',
'in:' . $visibleRoles->pluck('id')->implode(','),
new ListenerRoleRequiresListenerFeatureRule($team),
],
]
);
if ($validator->fails()) {
return;
}
$roles = $visibleRoles->whereIn('id', $roleIds);
$dto = new UserRolesSyncDTO(
user: $user,
activeUser: null,
roles: $roles,
);
$this->updateUserRolesAction->execute($dto);
}
public function deleteGroup($group): bool
{
$users = $group->members()->get();
foreach ($users as $user) {
$user->update(['group_id' => null]);
}
return $group->delete();
}
public function createNewGroup(CoreGroupRequest $dto, Team $team): ?Group
{
try {
/** @var Group|null $existingGroup */
$existingGroup = $team->groups()->withTrashed()->where('name', $dto->getDisplayName())->first();
if ($existingGroup) {
if ($existingGroup->getAttribute('deleted_at')) {
$existingGroup->restore();
}
return $existingGroup;
}
/** @var Group $newGroup */
$newGroup = $team->groups()->updateOrCreate(
['name' => $dto->getDisplayName()],
[
'slug' => str_replace(' ', '-', strtolower($dto->getDisplayName())),
'user_id' => $team->getOwner()->getId(),
'transcription_model_locale_id' => $team->getTranscriptionModelLocaleId(),
'default_timezone' => $team->getDefaultTimezone(),
'default_language' => $team->getDefaultLanguage(),
'country_code' => $team->getCountryCode(),
'playbook_id' => $team->getDefaultPlaybookId(),
],
);
return $newGroup;
} catch (Exception $exception) {
Sentry::captureException($exception);
return null;
}
}
public function updateGroupAttributesIfChanged(Group $group, CoreGroupRequest $dto, Team $team): Group
{
$actions = [];
if ($group->getName() !== $dto->getDisplayName()) {
$actions[] = $this->returnAction(
Constants::GROUP_PATCH_ATTRIBUTE_DISPLAY_NAME,
Constants::META_OPERATIONS_REPLACE,
$dto->getDisplayName(),
);
}
foreach ($actions as $action) {
$group = (new GroupPatchOperation($group, $action))->doUpdate();
}
return $group;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny_jupiter
Sync Changes
Hide This Notification
Code changed:
Hide
19
19
17
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE id = 1;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 283;
SELECT * FROM crm_fields WHERE id = 2234;
SELECT * FROM crm_field_values WHERE crm_field_id = 2234;
select * from crm_profiles where user_id = 143;
select * from record_types where crm_configuration_id = 39; # 0121K000001MHElQAO,0121K000001MHEqQAO
select * from business_processes where crm_configuration_id = 39;
# 01941000000H669AAC, 01941000000H66JAAS
select * from record_type_field_values
where record_type_id IN (24);
select * from crm_field_values where id IN (2730);
select * from crm_configurations where id = 39;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce'; #1035
select * from users where team_id = 1; # 222 group 3
SELECT * FROM activities WHERE user_id = 222 order by id desc;
select * from sidekick_settings where team_id = 1;
select * from teams where id = 1;
select * from team_features where team_id = 1;
select * from activities where crm_configuration_id = 2
and provider = 'ms-teams' and id = 608765;
SELECT * FROM activities WHERE crm_configuration_id = 2 and crm_provider_id = '59523413338';
select * from sidekick_settings where team_id = 2;
SELECT * FROM activities WHERE id = 608660;
select * from activity_summary_logs where activity_id = 608660;
select * from ai_prompts where transcription_id = 11214;
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('ed78a437-2804-450e-ab2f-56ab1c641346') = uuid;
# id: 608818, crm: 59628809737
SELECT * FROM activities WHERE uuid_to_bin('36b06e55-afdd-4782-8dee-c624cd0af191') = uuid;
# id: 608821, crm: 59632069252
SELECT ce.start_time, ce.end_time, a.id, a.uuid, crm_provider_id, calendar_event_id, title,
playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id,
scheduled_start_time, scheduled_end_time, actual_start_time, actual_end_time, a.created_at
FROM activities a
join calendar_events ce on a.calendar_event_id = ce.id
WHERE a.id IN (608818, 608821);
select * from users where team_id = 1;
select * from team_settings where team_id = 1;
select * from crm_profiles where crm_configuration_id = 39 order by user_id;
select * from team_features where team_id = 1;
select * from users where team_id = 2;
SELECT * FROM activities WHERE uuid_to_bin('ec7647e9-5225-458b-b475-f31aa2769204') = uuid; # 612639
# Preslava N. Ivanova, grou id 3
SELECT * FROM opportunities WHERE uuid_to_bin('a2928fe5-aec5-46cb-85d9-7654c89e46a6') = uuid;
select * from activities where opportunity_id = 344 and actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00';
select
a.id,
a.type,
a.scheduled_start_time,
a.actual_start_time,
a.created_at,
a.opportunity_id,
a.status
FROM activities a
WHERE opportunity_id = 344
and status IN ('completed', 'received', 'delivered')
and (
(a.actual_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.created_at between '2024-10-11 00:00:00' and '2024-10-12 00:00:00')
OR (a.scheduled_start_time between '2024-10-11 00:00:00' and '2024-10-12 00:00:00'))
;
SELECT * FROM users WHERE id = 222;
SELECT * FROM crm_profiles WHERE user_id = 222;
select * from crm_layouts where crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 281;
select * from group_deal_risk_types;
select * from opportunities where team_id = 1;
SELECT * FROM opportunities WHERE id = 315;
SELECT * FROM crm_field_data WHERE object_id = 315;
select * from crm_field_data where object_id = 260;
select * from generic_ai_prompts where subject_id = 315;
select * from teams; # 36, 21, 121, [EMAIL]
SELECT * FROM social_accounts WHERE sociable_id = 121 and provider = 'bullhorn';
# [PASSWORD_DOTS]
select * from teams where id = 1;
select * from crm_configurations where id = 39;
select * from users where team_id = 1;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 1;
# 1 - 00541000004281rAAA
# 204 - 0052g000003freeAAA
# 429 - 0052g000003qGOiAAM
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
select * from activities where type = 'softphone'
and created_at > '2024-12-11 15:24:36' order by id desc;
select * from activity_providers where team_id = 1;
select * from activity_provider_users where activity_provider_id = 328;
select * from opportunities where crm_configuration_id = 39
AND account_id = 178 AND is_closed = false
order by created_at DESC;
select * from contacts where id = 3952;
select * from accounts where id = 178;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations where id = 21;
select * from users where team_id = 36;
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 36
and sa.provider = 'bullhorn';
select * from social_accounts where id = 348;
UPDATE social_accounts SET
provider_user_token = '21442_6802599_91:41179a58-21e7-4d7c-ad58-56bb666b2f65',
provider_refresh_token = '21442_6802599_91:01c6b335-3f2a-42e4-85ff-8a08fa65fceb',
expires = 1733998131,
state = 'connected'
WHERE id = 348;
# [PASSWORD_DOTS]
select * from teams where id = 31;
select * from crm_configurations where id = 18;
select * from users where team_id = 31; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 31;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 31
and sa.provider = 'close';
select * from contacts where crm_configuration_id = 18;
# [PASSWORD_DOTS] NEPTUNE [PASSWORD_DOTS]
select * from teams;
select * from users where id IN (1030, 1035, 1052);
select * from crm_configurations;
select * from users where team_id = 65; # 257
select * from team_settings where team_id = 65; # 257
select * from invitations where team_id = 65; # 257
select * from users where email = '[EMAIL]'; # 257
select u.email, cp.* from users u
join crm_profiles cp on u.id = cp.user_id
where u.team_id = 65;
select * from crm_configurations where id = 53;
select * from accounts where crm_configuration_id = 53 order by id desc;
select * from leads where crm_configuration_id = 53 order by id desc;
select * from contacts where crm_configuration_id = 53 order by id desc;
select * from opportunities where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 53 order by id desc;
select * from crm_fields where crm_configuration_id = 53 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 53 order by id desc;
select * from stages where crm_configuration_id = 53 order by id desc;
select * from crm_profiles where crm_configuration_id = 13;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
and sa.provider = 'integration-app';
select * from contacts where crm_configuration_id = 13;
select * from social_accounts where sociable_id = 283;
SELECT * FROM opportunities WHERE crm_provider_id = '006O400000E9bzeIAB';
select * from activity_providers where team_id = 65;
SELECT * FROM activities WHERE crm_configuration_id IN (51, 52, 53);
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 65
;
# [PASSWORD_DOTS] STAGING [PASSWORD_DOTS]
SELECT * FROM teams;
SELECT * FROM teams WHERE id = 88;
SELECT * FROM teams WHERE id = 89;
select * from team_settings where team_id = 89;
SELECT * FROM users WHERE team_id = 89;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 89;
select * from users;
SELECT * FROM social_accounts WHERE sociable_id = 1761;
SELECT * FROM crm_configurations WHERE id = 70;
select * from accounts where crm_configuration_id = 70 order by id desc;
select * from leads where crm_configuration_id = 70 order by id desc;
select * from contacts where crm_configuration_id = 70 order by id desc;
select * from opportunities where crm_configuration_id = 70 order by id desc;
select * from crm_profiles where crm_configuration_id = 70 order by id desc;
select * from crm_fields where crm_configuration_id = 70 order by id desc;
select * from crm_field_values where crm_field_id = 3536 order by id desc;
select * from crm_layouts where crm_configuration_id = 70 order by id desc;
select * from stages where crm_configuration_id = 70 order by id desc;
select * from business_processes where crm_configuration_id = 70 order by id desc;
select * from business_process_stages where business_process_id = 34;
select * from contacts where id = 10468;
select * from crm_layouts where crm_configuration_id = 70;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 388;
SELECT * FROM crm_fields WHERE id IN (3533,3534,3535);
select * from activities where crm_configuration_id = 70
and (account_id IS NOT NULL or lead_id IS NOT NULL or contact_id IS NOT NULL or opportunity_id IS NOT NULL) order by id desc;
SELECT * FROM activities WHERE uuid_to_bin('2e10b60f-8a61-41c5-a3d4-28835353dc65') = uuid;
SELECT * FROM activities where crm_configuration_id = 69 ;
SELECT * FROM users WHERE email LIKE '%[EMAIL]%';
SELECT * FROM activities WHERE uuid_to_bin('5a150c93-40fc-42ec-b3bd-c1d328e09f6e') = uuid;
SELECT * FROM opportunities WHERE id = 385;
select * from participants p
join activities a on p.activity_id = a.id
where a.crm_configuration_id = 70
and (p.lead_id IS NOT NULL or p.contact_id IS NOT NULL);
SELECT * FROM participants WHERE id = 1013638;
select * from teams where id = 90;
select * from users where team_id = 90;
select * from social_accounts where social_accounts.sociable_id IN (1960,1760);
SELECT * FROM crm_profiles WHERE crm_configuration_id = 71;
select * from invitations where team_id = 90;
select * from crm_configurations where id = 71;
select * from accounts where crm_configuration_id = 71 order by id desc;
select * from leads where crm_configuration_id = 71 order by id desc;
select * from contacts where crm_configuration_id = 71 order by id desc;
select * from opportunities where crm_configuration_id = 71 order by id desc;
select * from crm_profiles where crm_configuration_id = 71 order by id desc;
select * from crm_fields where crm_configuration_id = 71 order by id desc;
select * from crm_field_values where crm_field_id = 3341 order by id desc;
select * from crm_layouts where crm_configuration_id = 71 order by id desc;
select * from stages where crm_configuration_id = 71 order by id desc;
select * from users order by secondary_email desc;
select u.id, u.email, u.status, sa.id, sa.provider_user_id from social_accounts sa
join users u on sa.sociable_id = u.id
where sa.provider = 'google' and u.email LIKE 'aneliya%';
select * from failed_jobs order by id desc;
select * from users where email = '[EMAIL]' or secondary_email = '[EMAIL]';
select * from teams;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 39;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type = 'task';
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 1
and sa.provider = 'salesforce';
# [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('c38b3895-fd0f-4b1f-9fb2-c170dba137c6') = uuid;
SELECT * FROM crm_configurations WHERE id = 70;
select * from teams where id = 1;
select * from groups where team_id = 1;
select * from users where team_id = 1;
select o.id, o.name,o.close_date, u.id, u.name, u.group_id, r.id, r.display_name, g.name, g.scope from opportunities o
join users u on o.user_id = u.id
join groups g on u.group_id = g.id
join role_user ru on u.id = ru.user_id
join roles r on ru.role_id = r.id
where o.crm_configuration_id = 39 and close_date > '2024-01-01 00:00:00';
select * from role_user where user_id = 143;
select * from roles;
select * from role_user;
select * from groups where id = 9;
select * from scope_groups where group_id = 9;
# [PASSWORD_DOTS]
select * from teams where id = 36;
select * from crm_configurations;
SELECT * FROM social_accounts WHERE sociable_id = 121;
https://crmsandbox.zoho.com/crm/jiminnyw4/tab/Leads/4776201000005049105
https://crmsandbox.zoho.com/crm/
https://crm.zoho.com/crm/org3469620/tab/Leads/230045000229559080
https://crm.zoho.com/crm/
org3469620
SELECT * FROM activities WHERE uuid_to_bin('03382d20-c8bc-48e7-a3d4-90b52fa5ceab') = uuid;
select * from users where email LIKE "%mobile_automation_%";
select * from social_accounts where sociable_id IN (2228);
select * from crm_profiles where user_id IN (2222,2223,2226,2227);
select * from teams order by id desc;
SELECT * FROM users WHERE id = 2229;
SELECT * FROM crm_profiles WHERE user_id = 2229;
select * from opportunities where crm_configuration_id = 88;
select * from crm_fields where crm_configuration_id = 88;
select * from crm_profiles where crm_configuration_id = 88;
SELECT * FROM teams WHERE id = 1;
SELECT * FROM users WHERE id = 143;
SELECT * FROM users WHERE uuid_to_bin('fde193d3-06a2-4e1a-8895-62b94039215d') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73385071-a756-42ae-9c73-8b53f2309467') = uuid;
https://app.staging.jiminny.com/ondemand?
min_duration=1
&
only_recorded=1
&
user_id%5B%5D=641f1acb-16b8-42d1-8726-df52979dad0e
&
sequence_number=2
select * from users where team_id = 1 and email like '%stoyan%'
select * from coaching_feedbacks;
select * from teams;
SELECT * FROM users WHERE team_id = 36;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from users where id = 143;
SELECT * FROM users WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM teams WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
SELECT * FROM activity_shares WHERE uuid_to_bin('73180eeb-33de-4065-977d-ccbe0e6c94fc') = uuid;
select * from users where team_id = 2;
select * from activities where crm_configuration_id = 39
and activities.scheduled_start_time BETWEEN '2025-04-09 00:00:00' AND '2025-04-09 23:59:59'
AND user_id = 143
order by id desc;
# [PASSWORD_DOTS]
select * from teams where id = 142; # 2312, 126
select * from team_settings;
select * from users where team_id = 142; # 21642
SELECT * FROM social_accounts WHERE sociable_id = 21642;
SELECT * FROM crm_profiles cp join users u ON u.id = cp.user_id WHERE team_id = 142;
select * from crm_profiles where id IN (93);
select * from invitations;
select * from team_features where team_id = 1;
SELECT * FROM crm_configurations WHERE id = 126;
select * from accounts where crm_configuration_id = 126 order by id desc;
select * from leads where crm_configuration_id = 126 order by id desc;
select * from contacts where crm_configuration_id = 126 order by id desc;
select * from opportunities where crm_configuration_id = 126 order by id desc;
select * from crm_profiles where crm_configuration_id = 126 order by id desc;
select * from crm_fields where crm_configuration_id = 126 # 11060
# and type IN ('picklist', 'status')
# and object_type = 'task'
order by id desc;
# 5731,5732,5733
select DISTINCT crm_field_id from crm_field_values where crm_field_id IN (11151,12239,12215,12185,12175,12165,12144,12137,12127,12109,12107,12105,12103,12092,12037,12005,12003,11987,11969,11958,11951,11942,11931,11924,11921,11917,11915,11901,11893,11883,11872,11870,11868,11866,11839,11833,11821,11793,11780,11777,11769,11757,11737,11735,11656,11645,11638,11629,11618,11611,11602,11591,11584,11581,11558,11544,11543,11534,11532,11529,11527,11503,11497,11493,11488,11470,11468,11457,11455,11397,11387,11372,11363,11348,11323,11318,11309,11301,11300,11292,11290,11286,11284,11256,11252,11242,11237,11233,11219,11176,11160) order by id desc;
select * from crm_layouts where crm_configuration_id = 126 order by id desc;
SELECT * FROM crm_layout_entities WHERE crm_layout_id in (300,299,298);
select * from stages where crm_configuration_id = 126 order by id desc;
select * from business_processes where crm_configuration_id = 126 order by id desc;
select * from business_process_stages where business_process_id IN (76,75,74,73);
select * from playbooks where team_id = 142;
select * from playbook_layouts where playbook_id IN (108);
SELECT * FROM playbook_categories WHERE playbook_id IN (108);
select * from teams where id = 130;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 2
and sa.provider = 'hubspot';
SELECT * FROM activities
WHERE crm_configuration_id = 110;
select * from teams;
select * from crm_configurations;
SELECT * FROM activities WHERE id = 628773;
SELECT * FROM crm_profiles WHERE user_id = 1460;
SELECT * FROM social_accounts WHERE sociable_id = 2291;
select * from teams;
select ru.*, pr.*, p.* from users u join role_user ru on ru.user_id = u.id
join permission_role pr on pr.role_id = ru.role_id
join permissions p on p.id = pr.permission_id
where team_id = 495 and p.name IN ('dial');
select * from teams where id = 145;
select * from crm_configurations where id = 129;
select * from social_accounts where sociable_id = 2317;
SELECT * FROM activities WHERE uuid_to_bin('8dbab184-a333-4268-ad57-fb41f8d53a9a') = uuid;
select * from teams where id = 1;
SELECT * FROM crm_layouts WHERE crm_configuration_id = 39;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 280;
SELECT * FROM crm_layout_entities WHERE id = 5507;
SELECT * FROM crm_fields WHERE crm_configuration_id = 39 and object_type IN ('event');
select * from teams;
select * from activities where crm_configuration_id = 14;
SELECT * FROM social_accounts where provider = 'copper';
select * from activities where id = 628467;
select * from participants where activity_id = 628467;
SELECT * FROM contacts WHERE id = 3969;
SELECT * FROM accounts WHERE id = 177;
SELECT * FROM activities WHERE uuid_to_bin('4eb54c77-cfa3-2bd4-84a7-9ed46a21c988') = uuid;
# [PASSWORD_DOTS] BH
select * from teams where id = 36;
SELECT * FROM crm_configurations WHERE id = 21;
select * from activities where crm_configuration_id = 21 and id = 607901;
select * from activities where crm_configuration_id = 21;
select * roles;
select * from permissions;
select * from permission_role where permission_id = 226;
select * from migrations order by id desc;
# mercury
# neptune
# earth
select * from teams;
select * from teams where id = 19;
select * from teams where id = 27;
select * from users where team_id = 27;
SELECT * FROM crm_configurations WHERE id = 42;
select * from social_accounts sa
join users u on sa.sociable_id = u.id
where u.team_id = 19
and sa.provider = 'pipedrive';
select * from activities where id = 631461;
SELECT * FROM crm_field_values WHERE crm_field_id = 180;
select * from teams where id = 2;
SELECT * FROM social_accounts WHERE sociable_id = 89;
SELECT * FROM activities WHERE uuid_to_bin('ba0c029a-bc14-4e17-8603-64174acebcbb') = uuid; # 634273
select * from activity_summary_logs where activity_id = 634273;
select * from sidekick_settings where team_id = 2;
select * from teams; # 2, 2
SELECT * FROM crm_configurations WHERE team_id = 2; # 2
select * from team_features where team_id = 2;
select * from features;
SELECT * FROM opportunities WHERE crm_configuration_id = 2 and crm_provider_id = '51317301383';
SELECT * FROM opportunities WHERE crm_configuration_id = 2 order by id desc;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from users where team_id = 1 and id IN (7160, 3248);
select * from migrations order by id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
select * from teams where id = 1;
select * from groups g JOIN playbooks p on g.playbook_id = p.id where g.team_id = 1;
select * from groups where id = 565;
select * from playbooks where team_id = 1;
select * from playbooks where id = 175;
select * from playbook_categories where playbook_id = 175;
select * from users where team_id = 1052;
select * from users where id = 7160;
select * from crm_profiles where user_id = 7160;
select * from features;
select
*
# id, uuid, type, provider, playbook_category_id, user_id, lead_id, contact_id, account_id, opportunity_id, stage_id,
# crm_configuration_id, crm_provider_id, transcription_id, status
from activities where crm_configuration_id = 1 and type = 'conference'
# and crm_provider_id IS NOT NULL
and provider != 'uploader' and actual_start_time IS NOT NULL
ORDER by id desc;
select * from activities where id = 54747783; # 00UO400000pCzojMAC
select p.id, p.activity_type, pc.id, pc.name
FROM playbooks p
join playbook_categories pc on p.id = pc.playbook_id
where p.team_id = 1 and p.activity_type = 'event';
SELECT * FROM crm_fields WHERE crm_configuration_id = 1 and object_type = 'event';
SELECT * FROM crm_field_values WHERE crm_field_id = 4;
select * from crm_layouts cl join playbook_layouts pl on cl.id = pl.layout_id
where crm_configuration_id = 1 and pl.playbook_id = 175;
select * from teams;
SELECT r.* FROM automated_reports r
join teams t on r.team_id = t.id
WHERE r.frequency = 'daily'
and r.status = 1
AND t.status = 'active'
AND (r.expires_at >= now() OR r.expires_at IS NULL);
select * from automated_report_results where report_id IN (18, 33);
select * from users where team_id = 1 and id = 1047;
SELECT * FROM social_accounts WHERE sociable_id = 1047;
select * from activity_searches where id = 10932;
select * from activity_search_filters where activity_search_id = 10932;
select * from automated_reports order by id desc;
select * from automated_report_results order by id desc;
select * from automated_reports where id IN (55);
select * from automated_report_results where id IN (81);
select * from users where id IN (10633, 13987, 11985);
select * from users where group_id IN (3710);
SELECT * FROM automated_reports WHERE uuid_to_bin('18a06a75-afd2-476f-aadc-14d4057bdda2') = uuid;
SELECT * FROM automated_report_results WHERE uuid_to_bin('582d4b50-8cd3-42a9-9819-d676ff8f3b43') = uuid;
select * from teams;
select * from accounts where team_id = 1;
select * from automated_report_results where media_type = 'pdf' and status = 2;
SELECT * FROM automated_report_results WHERE uuid_to_bin('82e74956-6144-4cd1-a3d3-af985c3070a4') = uuid;
select * from teams where id = 1029;
select * from crm_configurations where provider = 'pipedrive';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1029 and sa.provider = 'pipedrive';
[
{
"user_id": "23460 (owner)",
"email": "[EMAIL]",
"id": 69,
"sociable_id": 23460,
"provider_user_id": "19555731",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:rYyABXmXsBhEdYU_dfmDH8GF-vzSseJXE5bds_zAyVdAwlTXOPdTl9i4PS4jVofLvpq7IRgvEt2BzGhR6cWiQXHHD0AtayQOkZm262ClFCsMYtKGfep0Jq1n0eiRIVqT9gAY7rWvhpEDF8oAlgnRGmqx-euIkpzE79sPXh4OjNx_yUIaanjyplGpBBJ_NiACd1sMlZmseyUyyU_gldqlCBAuK9hhATc9icgg7zuoc7nKBBrlg49tRtzEagDh6xbFBpzfCp7kE_7n4TLWfWHLPMzu-bktjwA969G9sFRmoH1GjPA0a2odDT4dk1_1ouBrB1NcTT2hQUqH-_RzDW2nWmeoVHA",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]b2bfc",
"expires": 1779091997,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "connected",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 08:23:28",
"updated_at": "2026-05-18 07:13:18",
"provider_user_token_encrypted": "eyJpdiI6Ik9oYzBwcTVteWN4ajBRaDdMb0FjWGc9PSIsInZhbHVlIjoiQUNMbjU5UHR2Q1RnbWRXMEU1TUx6UVpRU3gzdVc5WktmTE4rVlhXa3lRaGhyUUlZMVZRWEJuR0JaWWhZZXNPRlBuanhuYU5MVHZ5TG9NTVVjNjJSUUpZZ2VhbGYxbHg0UzJEdTVmQjNFZnJRZkMwYjd0N2RMZ05GRS9IR3c2K0NoVjBjYTA5UG12SkxHeDlDMGVNN3ptUWUzblFiTngyYzR1eUpHSEYrdEwvZm0yZklGYjBSNEtTR2ZGazhLM1hqT3lVbjFobDNPZ0d3anFlcjhKcXpERlZGOVN1YmFyNDIvM1BFRDFMYnp4WEI4TGVLM2xYcy9CL0RDOWlQNHI3N0NwWnJPMWRtZllmM2ZKeE9TV2NBeDZxL2M1YnlSVzd3ZW96T3F1QmtBYXBHYkUraGcvdCtRajlYZXBjVVBSdFlMUjVPVDVJbDdyenVoWjMrbVJvU3ZZR1dQZ3pqQ3F3aDF2U2xPZWZIN3BCWVFLNXpxQUtDb2pIK0xHc1E3SklSM3Q0VkNSbm9oK2pFK3hLaW54T1dWbEVneUp0RGhhdVBuOFI4MXROc3dZWnFnTUpiaDVMMnZ4QmlRM3k4QWFlMVFWUFYvdGhJQzZBYnhBQmhWa2ZKN1ZhSnhpaExxbmlTemgzUWw3aXJtWjlSMlhmd0lWMDNDN1N3My9Ua0hCL2xqY3RkVFhMSjFJMDRjOE5DWlgrZ3FMVXN6RWlwUE5GWERZdG1xVjVxOFlLRGs2VVJKS3FLeWRxQjYxdDh4Z2JJNXhlWEZ3dkQ4SGtybDNUcndzblFHeVJNRkYraFh2UDFIUTdMQ1BZa3dEU1dBbzk5K0dyT2RNVFBZZUJpRytSck5pYlI1YUZyMmhUNEZCdWxHYmJLREtzbUpjVkhvV0RoejJpbm1SWHlNaXE5M0RhcS94UW9EdFoweWF3bVFVY0dTZWFPSXBmOCtDYndia215cmtyZU1oT0Exam1CV2tPblNhYjY4clVEeUs3anVHUmNHeS9YLzRha1VhbGl3N3lwaDlzZnRhQUZta2s4eFllNHgzRklSRmNyazJ4dlBDMnByNCtBRjNaVjJCTT0iLCJtYWMiOiJkYTQxZDY1OTY2ZTljMTgyZWRhNGEzMGZjZDc2MjBjN2NlNzU2YTViNGQxNWE1NTI2ZmI1MWQyYjQ2ODYxZmEwIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6Imt2bGxlSmxUK05GMjF0dEtPaTMrUlE9PSIsInZhbHVlIjoiUXZHTElZRXkreHFxUU02SnZ4eVBacG9WWTRlVkd0USszV3JyVFlpU2ZaY25GSWo2WFcrRzNlbFRlUXRQczNwSXRCcEdvZEpveG9jMzBDSTgwdnZLQnc9PSIsIm1hYyI6ImQxYWI0NzU5Nzg5MDI4YWVhZmQ4Mjg1YzhkZDQzMjRkYWYwYTdhZTY5MDMxMjc0OWNiYjY0Nzc3NDQ0MTEyY2EiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300786192D9D96DD60D3D1EBC9DFAEE5F0C45EE80165CF3F3D2B3B627026AA7CFC7CA0128DD463535D32EE491ADBADF8B07596B0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040C7FB1319048ECB2EA3F23B995020110802B52D22F5EAD341AB238FBBCB6093156E443876A664BA5555D722565C2B2D04422C868CD7350555E3CC74221",
"sociable_type": "user",
"owner_id": 23460
},
{
"user_id": "23463",
"email": "[EMAIL]",
"id": 72,
"sociable_id": 23463,
"provider_user_id": "23270841",
"provider_user_token": "v1u:AQIBAHj-LzTNK2yuuuaLqifzhWb9crUNKTpk4FlQ9rjnXqp_6AEQhDhDQVa1nvWCHEvnpvSEAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnG8KNcZLIjEnlRPxAgEQgDsGPIcKjsMU7Qel36BtM5FCQa56mYUy24_AAoqd12yjVFkq6egLqS0inp-5G4JE7frJURMV8VTw_fY14g:txqCuWLeVhgwiaFqXIvQWWrtrnFIy_4lT3VCr-sRB4g6_2lK8KcQ_6ka_qFmZhr-IeIAKmAImx6H1iIKx4Ab7XZ5MnKIh03GKbHjI0n0rGT9UYkeH21jKOxJvKaSX_TyLbxFPR6irPQyvqcpBClXI52gVJH01KzZy_dMTHFXhhDLOIhEpSrQXHG7Qo8q7OuBeSPZrU1ALi9kmAm4GTpzGTbzfl-hUt9IAfPunJOCyv3mf2Tl-MT8EyQgOFPrsP3yz9UlSyVhb40zO_bCnUrqNxjwgm_E6vgpVrwULTQbHe-43Dq-TRetjceUzT88GBgVJ0UdxXP5BRBVXcL5ir8-9ZTMaNU",
"provider_refresh_token": "5034113:[TELEGRAM_TOKEN]78ad1",
"expires": 1753837219,
"refresh_token_expires": null,
"provider": "pipedrive",
"state": "full-refresh",
"auth_scope": "base,deals:full,activities:full,contacts:full,search:read",
"retry_after": null,
"created_at": "2025-04-16 10:41:12",
"updated_at": "2025-07-30 01:00:17",
"provider_user_token_encrypted": "eyJpdiI6InVEVEl2SzIxMjd1bkNDWG9lY3YvQ0E9PSIsInZhbHVlIjoiRlJLbDZ3ZHo2dHMxUWQwdGU2YUZjV3lPWHlxQTJ0eWh4S0RTMjlSaThVcktoaWhXcTd2UXl4Mjg4bW5UUnZCZEQ5NXpuQTVKOURiMDNIa3l3K0lSWCt5azRBOEdHbitWQXhxeEpMVUZ1dnF2NVl1TTZLelZOaGNvRlBLeGpIWlpoRGloUEprd2xoNUFPcTlLcUd3WVlUU2svR1NOeXBYQ2NnMWhnK1V2aytOeVVMNzJGdVZXMU1JS3BSaGNCcmxkVjEwQ01mQXNBdWNhS1lMZWZobnZwcHBkN1R4bUVDRUNYdnNtSVJkdG5MdkN3djJBT0hMRDl1MHFGbnl4WU13ejBkUWsrdUljWkZhcTJlN0JDSGdTVzlPY0FGMUJlZi9WRGpkMUk5R20wblYwSk9VR2FuaHpLTzJNeitMbnF1V1NEMUUxRmYzaDRGZDMyaXd3Z0FjQno4SzVoYjUyTmV3UXNpRlF4TGZKNVl3dUFqdGhKVWJjRVlUUXRGalBpaXJvSGJmbS8rd25aQ2Zvc05saHRDRjlHV1VEUFFiRU5xbWRVNkxFSXV0RUZyaUlYNWMwMmhnZ0Y1VUQ4eEFkY2QyWXpnR0NidkVJSWdjVGljUjA3NDdpZW9WUHhtSlpGSGdNU2hRUTA5ZW03RGpiRFdrdytkOHJXSUxlazZNaG9iaUg2NFZYdEc3YklMeFZvblBzWmVRSDcvN2M4WUNtL3h4S2IrUW00cXhialBia3BJcW5XallBNlV5WWdhcE1ZVFBBM3RSSUVBamYvOGZEQWM5a2FJMGwyWkRSU3dlTEtPemZlQ3RXRGNDcEdYRHdMNTlTQVg2SUdUN0hVaXdZT1dUOUlrVzkrZHFBemhwWXg1cm4rSy9UOHUzcnNSM2dISlhBRTEyVUNyTkZYaFJYUlN1a2RKVHhhM2dHckR3a1JGaVZ2Wk9BVnhTclVpSEhwWTVpQTlJbXVkOUxSTGpRbDk0a1VtbE9QMVAvN3VlVEhJUHd2elowd0laNVIzZ3M3N0ZOK0NDakIwQ2FicGxoMDBhTXI0VUppUmFOZHdlWUdGV21NNFQ4RU1nY0dnWT0iLCJtYWMiOiI0ZTU4ZmJkNTdkYmY0NGE4NTJjZjlhNDExNzE2YjhlOWM2NTA5OGY2MDA4OTcyZDVlOTljY2JjZDhmMjBhMDUyIiwidGFnIjoiIn0=",
"provider_refresh_token_encrypted": "eyJpdiI6IkJGMkdRVHRKM2VTcitKNGcvQWJtUGc9PSIsInZhbHVlIjoicmFyRkxPZ1Rybm1ORXlEVjJ2TXFGTzJtM3hWaFhnUVVHN2ZlR1lRM0I5d3ozbnZTcU5EdzJqRkI2elhyNWhlenRTUXV3bjk0N1JXeklDMVAyUzBKcHc9PSIsIm1hYyI6ImJhODVjMGQyZDE3Y2ExNjc2OWVjYWJiNmFjYWVkODIyMTMyNWVhYTExMTgwYTEyMTU0MzUzZGE1YjQ5YzQ5ZjEiLCJ0YWciOiIifQ==",
"encryption_key": "0x01020300788C37CDF66ABE9301A68D5D4866AC0C197E04EEE4D904F20A59991322EBAE252301BEF4B24FF01359E934E5654617E4EEAC0000006E306C06092A864886F70D010706A05F305D020100305806092A864886F70D010701301E060960864801650304012E3011040CEB00EF45BDEA999A5558889E020110802B925F372F7BEFAF0B45E48686113D1DA430ECFCC07B1F61BA6828CC44235278EDB05C486E8068D0BE737D91",
"sociable_type": "user",
"owner_id": 23460
}
]...
|
53497
|
NULL
|
NULL
|
NULL
|