diff --git a/app-modules/interaction/database/factories/InteractionConfidentialTeamFactory.php b/app-modules/interaction/database/factories/InteractionConfidentialTeamFactory.php new file mode 100644 index 0000000000..159ba7e2fa --- /dev/null +++ b/app-modules/interaction/database/factories/InteractionConfidentialTeamFactory.php @@ -0,0 +1,61 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Interaction\Database\Factories; + +use AdvisingApp\Interaction\Models\Interaction; +use AdvisingApp\Interaction\Models\InteractionConfidentialTeam; +use AdvisingApp\Team\Models\Team; +use Illuminate\Database\Eloquent\Factories\Factory; + +/** + * @extends Factory + */ +class InteractionConfidentialTeamFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'interaction_id' => Interaction::factory(), + 'team_id' => Team::factory(), + ]; + } +} diff --git a/app-modules/interaction/database/factories/InteractionConfidentialUserFactory.php b/app-modules/interaction/database/factories/InteractionConfidentialUserFactory.php new file mode 100644 index 0000000000..5e85726e0a --- /dev/null +++ b/app-modules/interaction/database/factories/InteractionConfidentialUserFactory.php @@ -0,0 +1,61 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Interaction\Database\Factories; + +use AdvisingApp\Interaction\Models\Interaction; +use AdvisingApp\Interaction\Models\InteractionConfidentialUser; +use App\Models\User; +use Illuminate\Database\Eloquent\Factories\Factory; + +/** + * @extends Factory + */ +class InteractionConfidentialUserFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'interaction_id' => Interaction::factory(), + 'user_id' => User::factory(), + ]; + } +} diff --git a/app-modules/interaction/database/migrations/2025_01_24_141857_add_is_confidential_to_interactions_table.php b/app-modules/interaction/database/migrations/2025_01_24_141857_add_is_confidential_to_interactions_table.php new file mode 100644 index 0000000000..ba9dbd6f49 --- /dev/null +++ b/app-modules/interaction/database/migrations/2025_01_24_141857_add_is_confidential_to_interactions_table.php @@ -0,0 +1,55 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + public function up(): void + { + Schema::table('interactions', function (Blueprint $table) { + $table->boolean('is_confidential')->default(false); + }); + } + + public function down(): void + { + Schema::table('interactions', function (Blueprint $table) { + $table->dropColumn('is_confidential'); + }); + } +}; diff --git a/app-modules/interaction/database/migrations/2025_01_24_162843_create_interaction_confidential_users_table.php b/app-modules/interaction/database/migrations/2025_01_24_162843_create_interaction_confidential_users_table.php new file mode 100644 index 0000000000..fa19c6407f --- /dev/null +++ b/app-modules/interaction/database/migrations/2025_01_24_162843_create_interaction_confidential_users_table.php @@ -0,0 +1,56 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + public function up(): void + { + Schema::create('interaction_confidential_users', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->foreignUuid('interaction_id')->constrained()->cascadeOnDelete(); + $table->foreignUuid('user_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('interaction_confidential_users'); + } +}; diff --git a/app-modules/interaction/database/migrations/2025_01_24_162901_create_interaction_confidential_teams_table.php b/app-modules/interaction/database/migrations/2025_01_24_162901_create_interaction_confidential_teams_table.php new file mode 100644 index 0000000000..e4f5f1df99 --- /dev/null +++ b/app-modules/interaction/database/migrations/2025_01_24_162901_create_interaction_confidential_teams_table.php @@ -0,0 +1,56 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + public function up(): void + { + Schema::create('interaction_confidential_teams', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->foreignUuid('interaction_id')->constrained()->cascadeOnDelete(); + $table->foreignUuid('team_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('interaction_confidential_teams'); + } +}; diff --git a/app-modules/interaction/database/migrations/2025_01_29_043853_data_activate_confidential_interaction_feature.php b/app-modules/interaction/database/migrations/2025_01_29_043853_data_activate_confidential_interaction_feature.php new file mode 100644 index 0000000000..f612c71962 --- /dev/null +++ b/app-modules/interaction/database/migrations/2025_01_29_043853_data_activate_confidential_interaction_feature.php @@ -0,0 +1,50 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use App\Features\ConfidentialInteractionFeatureFlag; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + ConfidentialInteractionFeatureFlag::activate(); + } + + public function down(): void + { + ConfidentialInteractionFeatureFlag::deactivate(); + } +}; diff --git a/app-modules/interaction/src/Filament/Concerns/HasManyMorphedInteractionsTrait.php b/app-modules/interaction/src/Filament/Concerns/HasManyMorphedInteractionsTrait.php index 56ad30c355..d16360e5ba 100644 --- a/app-modules/interaction/src/Filament/Concerns/HasManyMorphedInteractionsTrait.php +++ b/app-modules/interaction/src/Filament/Concerns/HasManyMorphedInteractionsTrait.php @@ -38,6 +38,7 @@ use AdvisingApp\Interaction\Models\Interaction; use AdvisingApp\Prospect\Models\Prospect; +use App\Features\ConfidentialInteractionFeatureFlag; use App\Filament\Tables\Columns\IdColumn; use Carbon\CarbonInterface; use Filament\Infolists\Components\Fieldset; @@ -49,6 +50,7 @@ use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Illuminate\Support\HtmlString; trait HasManyMorphedInteractionsTrait { @@ -56,6 +58,12 @@ public function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ + TextEntry::make('is_confidential') + ->columnSpanFull() + ->label('') + ->badge() + ->formatStateUsing(fn ($state): string => $state ? 'Confidential' : '') + ->visible(fn ($record): bool => ConfidentialInteractionFeatureFlag::active() && $record->is_confidential), TextEntry::make('user.name') ->label('Created By'), Fieldset::make('Details') @@ -94,7 +102,32 @@ public function table(Table $table): Table ->recordTitleAttribute('id') ->columns([ IdColumn::make(), - TextColumn::make('initiative.name'), + TextColumn::make('initiative.name') + ->description( + function (Interaction $record) { + if (! ConfidentialInteractionFeatureFlag::active() || ! $record->is_confidential) { + return null; + } + + return new HtmlString( + << +
+
+ + + + Confidential + + + +
+
+ + HTML + ); + } + ), TextColumn::make('driver.name'), TextColumn::make('division.name'), TextColumn::make('outcome.name'), diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php index c7f800bcf9..52e0b7c685 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php @@ -49,8 +49,10 @@ use AdvisingApp\Interaction\Models\InteractionType; use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\StudentDataModel\Models\Student; +use App\Features\ConfidentialInteractionFeatureFlag; use App\Models\Scopes\ExcludeConvertedProspects; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\MorphToSelect; @@ -112,6 +114,28 @@ public function form(Form $form): Form ->titleAttribute('case_number'), ]) ->hiddenOn([RelationManager::class, ManageRelatedRecords::class]), + Fieldset::make('Confidentiality') + ->schema([ + Checkbox::make('is_confidential') + ->label('Confidential') + ->live() + ->columnSpanFull(), + Select::make('interaction_confidential_users') + ->relationship('confidentialAccessUsers', 'name') + ->preload() + ->label('Users') + ->multiple() + ->exists('users', 'id') + ->visible(fn (Get $get) => $get('is_confidential')), + Select::make('interaction_confidential_teams') + ->relationship('confidentialAccessTeams', 'name') + ->preload() + ->label('Teams') + ->multiple() + ->exists('teams', 'id') + ->visible(fn (Get $get) => $get('is_confidential')), + ]) + ->visible(fn (): bool => ConfidentialInteractionFeatureFlag::active()), Fieldset::make('Details') ->schema([ Select::make('interaction_initiative_id') diff --git a/app-modules/interaction/src/Models/Interaction.php b/app-modules/interaction/src/Models/Interaction.php index 34d22730d8..219fe2051c 100644 --- a/app-modules/interaction/src/Models/Interaction.php +++ b/app-modules/interaction/src/Models/Interaction.php @@ -41,7 +41,8 @@ use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\CaseManagement\Models\CaseModel; use AdvisingApp\Division\Models\Division; -use AdvisingApp\Interaction\Providers\InteractionServiceProvider; +use AdvisingApp\Interaction\Models\Scopes\InteractionConfidentialScope; +use AdvisingApp\Interaction\Observers\InteractionObserver; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\Prospect\Models\Prospect; @@ -49,6 +50,7 @@ use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Student; +use AdvisingApp\Team\Models\Team; use AdvisingApp\Timeline\Models\Contracts\ProvidesATimeline; use AdvisingApp\Timeline\Models\Timeline; use AdvisingApp\Timeline\Timelines\InteractionTimeline; @@ -57,9 +59,11 @@ use App\Models\User; use Exception; use Illuminate\Database\Eloquent\Attributes\ObservedBy; +use Illuminate\Database\Eloquent\Attributes\ScopedBy; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\SoftDeletes; @@ -69,7 +73,7 @@ /** * @mixin IdeHelperInteraction */ -#[ObservedBy([InteractionServiceProvider::class])] +#[ObservedBy([InteractionObserver::class])] #[ScopedBy(InteractionConfidentialScope::class)] class Interaction extends BaseModel implements Auditable, CanTriggerAutoSubscription, ExecutableFromACampaignAction, ProvidesATimeline { use AuditableTrait; @@ -91,11 +95,13 @@ class Interaction extends BaseModel implements Auditable, CanTriggerAutoSubscrip 'start_datetime', 'subject', 'user_id', + 'is_confidential', ]; protected $casts = [ 'start_datetime' => 'datetime', 'end_datetime' => 'datetime', + 'is_confidential' => 'boolean', ]; public function user(): BelongsTo @@ -199,6 +205,20 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s // Do we need to be able to relate campaigns/actions to the RESULT of their actions? } + public function confidentialAccessUsers(): BelongsToMany + { + return $this->belongsToMany(User::class, 'interaction_confidential_users') + ->using(InteractionConfidentialUser::class) + ->withTimestamps(); + } + + public function confidentialAccessTeams(): BelongsToMany + { + return $this->belongsToMany(Team::class, 'interaction_confidential_teams') + ->using(InteractionConfidentialTeam::class) + ->withTimestamps(); + } + protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { diff --git a/app-modules/interaction/src/Models/InteractionConfidentialTeam.php b/app-modules/interaction/src/Models/InteractionConfidentialTeam.php new file mode 100644 index 0000000000..82c7252f44 --- /dev/null +++ b/app-modules/interaction/src/Models/InteractionConfidentialTeam.php @@ -0,0 +1,58 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Interaction\Models; + +use AdvisingApp\Team\Models\Team; +use Illuminate\Database\Eloquent\Concerns\HasUuids; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\Pivot; + +class InteractionConfidentialTeam extends Pivot +{ + use HasFactory; + use HasUuids; + + public function interaction() + { + return $this->belongsTo(Interaction::class); + } + + public function team() + { + return $this->belongsTo(Team::class); + } +} diff --git a/app-modules/interaction/src/Models/InteractionConfidentialUser.php b/app-modules/interaction/src/Models/InteractionConfidentialUser.php new file mode 100644 index 0000000000..6b533d0a29 --- /dev/null +++ b/app-modules/interaction/src/Models/InteractionConfidentialUser.php @@ -0,0 +1,58 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Interaction\Models; + +use App\Models\User; +use Illuminate\Database\Eloquent\Concerns\HasUuids; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\Pivot; + +class InteractionConfidentialUser extends Pivot +{ + use HasFactory; + use HasUuids; + + public function interaction() + { + return $this->belongsTo(Interaction::class); + } + + public function user() + { + return $this->belongsTo(User::class); + } +} diff --git a/app-modules/interaction/src/Models/Scopes/InteractionConfidentialScope.php b/app-modules/interaction/src/Models/Scopes/InteractionConfidentialScope.php new file mode 100644 index 0000000000..18f3146f4b --- /dev/null +++ b/app-modules/interaction/src/Models/Scopes/InteractionConfidentialScope.php @@ -0,0 +1,70 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Interaction\Models\Scopes; + +use App\Features\ConfidentialInteractionFeatureFlag; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Scope; + +class InteractionConfidentialScope implements Scope +{ + /** + * Apply the scope to a given Eloquent query builder. + */ + public function apply(Builder $builder, Model $model): void + { + if (! ConfidentialInteractionFeatureFlag::active() || auth()->user()?->IsAdmin) { + return; + } + + $builder->where('is_confidential', false)->orWhere(function (Builder $query) { + $query->where('is_confidential', true) + ->where(function (Builder $query) { + $query->where('user_id', auth()->id()) + ->orWhereHas('confidentialAccessTeams', function (Builder $query) { + $query->whereHas('users', function (Builder $query) { + $query->where('user_id', auth()->id()); + }); + }) + ->orWhereHas('confidentialAccessUsers', function (Builder $query) { + $query->where('user_id', auth()->id()); + }); + }); + }); + } +} diff --git a/app-modules/interaction/tests/Filament/InterationRelationManager/ListIneractionManagerTest.php b/app-modules/interaction/tests/Filament/InterationRelationManager/ListIneractionManagerTest.php new file mode 100644 index 0000000000..8d1ec5c964 --- /dev/null +++ b/app-modules/interaction/tests/Filament/InterationRelationManager/ListIneractionManagerTest.php @@ -0,0 +1,89 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\Interaction\Filament\Resources\InteractionResource\Pages\ListInteractions; +use AdvisingApp\Interaction\Models\Interaction; +use AdvisingApp\Team\Models\Team; +use App\Models\User; + +use function Pest\Laravel\actingAs; +use function Pest\Livewire\livewire; +use function Tests\asSuperAdmin; + +test('ListInteration with display data using the is_confidential field', function () { + $user = User::factory()->licensed(LicenseType::cases())->create(); + $user->givePermissionTo('interaction.view-any'); + + $userWithoutAttach = User::factory()->licensed(LicenseType::cases())->create(); + $userWithoutAttach->givePermissionTo('interaction.view-any'); + + $teamUser = User::factory()->licensed(LicenseType::cases())->create(); + $teamUser->givePermissionTo('interaction.view-any'); + + $team = Team::factory()->hasAttached($teamUser, [], 'users')->create(); + + $confidentialInteraction = Interaction::factory()->hasAttached($user, [], 'confidentialAccessUsers')->hasAttached($team, [], 'confidentialAccessTeams')->count(10)->create([ + 'is_confidential' => true, + ]); + + $nonConfidentialInteraction = Interaction::factory()->count(10)->create([ + 'is_confidential' => false, + ]); + + $allInteractions = $confidentialInteraction->merge($nonConfidentialInteraction); + + actingAs($user); + livewire(ListInteractions::class) + ->set('tableRecordsPerPage', 20) + ->assertCanSeeTableRecords($allInteractions); + + actingAs($userWithoutAttach); + livewire(ListInteractions::class) + ->set('tableRecordsPerPage', 10) + ->assertCanSeeTableRecords($nonConfidentialInteraction) + ->assertCanNotSeeTableRecords($confidentialInteraction); + + actingAs($teamUser); + livewire(ListInteractions::class) + ->set('tableRecordsPerPage', 20) + ->assertCanSeeTableRecords($allInteractions); + + asSuperAdmin(); + livewire(ListInteractions::class) + ->set('tableRecordsPerPage', 20) + ->assertCanSeeTableRecords($allInteractions); +}); diff --git a/app/Features/ConfidentialInteractionFeatureFlag.php b/app/Features/ConfidentialInteractionFeatureFlag.php new file mode 100644 index 0000000000..efb04b14ad --- /dev/null +++ b/app/Features/ConfidentialInteractionFeatureFlag.php @@ -0,0 +1,47 @@ + + + Copyright © 2016-2025, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Features; + +use App\Support\AbstractFeatureFlag; + +class ConfidentialInteractionFeatureFlag extends AbstractFeatureFlag +{ + public function resolve(mixed $scope): mixed + { + return false; + } +}