Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions app/Audit/AbstractAuditLogFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,22 @@ final public function setContext(AuditContext $ctx): void
$this->ctx = $ctx;
}

protected function getUserInfo(): string
{
if (!$this->ctx) {
return 'Unknown (unknown)';
}

$user_name = 'Unknown';
if ($this->ctx->userFirstName || $this->ctx->userLastName) {
$user_name = trim(sprintf("%s %s", $this->ctx->userFirstName ?? '', $this->ctx->userLastName ?? '')) ?: 'Unknown';
} elseif ($this->ctx->userEmail) {
$user_name = $this->ctx->userEmail;
}

$user_id = $this->ctx->userId ?? 'unknown';
return sprintf("%s (%s)", $user_name, $user_id);
}

abstract public function format($subject, array $change_set): ?string;
}
2 changes: 1 addition & 1 deletion app/Audit/AuditLogFormatterFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function make(AuditContext $ctx, $subject, $eventType): ?IAuditLogFormatt
if (count($subject) > 0) {
$child_entity = $subject[0];
}
if (is_null($child_entity) && count($subject->getSnapshot()) > 0) {
if (is_null($child_entity) && isset($subject->getSnapshot()[0]) && count($subject->getSnapshot()) > 0) {
$child_entity = $subject->getSnapshot()[0];
}
$child_entity_formatter = $child_entity != null ? ChildEntityFormatterFactory::build($child_entity) : null;
Expand Down
97 changes: 97 additions & 0 deletions app/Audit/ConcreteFormatters/FeaturedSpeakerAuditLogFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace App\Audit\ConcreteFormatters;

/**
* Copyright 2025 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

use App\Audit\AbstractAuditLogFormatter;
use App\Audit\Interfaces\IAuditStrategy;
use App\Models\Foundation\Summit\Speakers\FeaturedSpeaker;
use Illuminate\Support\Facades\Log;

class FeaturedSpeakerAuditLogFormatter extends AbstractAuditLogFormatter
{
private string $event_type;

public function __construct(string $event_type)
{
$this->event_type = $event_type;
}

public function format($subject, array $change_set): ?string
{
if (!$subject instanceof FeaturedSpeaker) {
return null;
}

try {
$speaker = $subject->getSpeaker();
$speaker_email = $speaker ? ($speaker->getEmail() ?? 'unknown') : 'unknown';
$speaker_name = $speaker ? sprintf("%s %s", $speaker->getFirstName() ?? '', $speaker->getLastName() ?? '') : 'Unknown';
$speaker_name = trim($speaker_name) ?: $speaker_name;
$speaker_id = $speaker ? ($speaker->getId() ?? 'unknown') : 'unknown';

$summit = $subject->getSummit();
$summit_name = $summit ? ($summit->getName() ?? 'Unknown Summit') : 'Unknown Summit';

$order = $subject->getOrder();

switch ($this->event_type) {
case IAuditStrategy::EVENT_ENTITY_CREATION:
return sprintf(
"Speaker '%s' (%s) added as featured speaker for Summit '%s' with display order %d by user %s",
$speaker_name,
$speaker_id,
$summit_name,
$order,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$changed_fields = [];

if (isset($change_set['Order'])) {
$old_order = $change_set['Order'][0] ?? 'unknown';
$new_order = $change_set['Order'][1] ?? 'unknown';
$changed_fields[] = sprintf("display_order %s → %s", $old_order, $new_order);
}
if (isset($change_set['PresentationSpeakerID'])) {
$changed_fields[] = "speaker";
}

$fields_str = !empty($changed_fields) ? implode(', ', $changed_fields) : 'properties';
return sprintf(
"Featured speaker '%s' (%s) updated (%s changed) by user %s",
$speaker_name,
$speaker_id,
$fields_str,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Speaker '%s' (%s) removed from featured speakers list of Summit '%s' by user %s",
$speaker_name,
$speaker_id,
$summit_name,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("FeaturedSpeakerAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
107 changes: 107 additions & 0 deletions app/Audit/ConcreteFormatters/PresentationSpeakerAuditLogFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace App\Audit\ConcreteFormatters;

/**
* Copyright 2025 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

use App\Audit\AbstractAuditLogFormatter;
use App\Audit\Interfaces\IAuditStrategy;
use models\summit\PresentationSpeaker;
use Illuminate\Support\Facades\Log;

class PresentationSpeakerAuditLogFormatter extends AbstractAuditLogFormatter
{
private string $event_type;

public function __construct(string $event_type)
{
$this->event_type = $event_type;
}

public function format($subject, array $change_set): ?string
{
if (!$subject instanceof PresentationSpeaker) {
return null;
}

try {
$full_name = sprintf("%s %s", $subject->getFirstName() ?? 'Unknown', $subject->getLastName() ?? 'Unknown');
$email = $subject->getEmail() ?? 'unknown';
$speaker_id = $subject->getId() ?? 'unknown';

switch ($this->event_type) {
case IAuditStrategy::EVENT_ENTITY_CREATION:
$bio = $subject->getBio() ? sprintf(" - Bio: %s", mb_substr($subject->getBio(), 0, 50)) : '';
return sprintf(
"Speaker '%s' (%s) created with email '%s'%s by user %s",
$full_name,
$speaker_id,
$email,
$bio,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$changed_fields = [];
if (isset($change_set['FirstName']) || isset($change_set['LastName'])) {
$changed_fields[] = "name";
}
if (isset($change_set['Email'])) {
$changed_fields[] = "email";
}
if (isset($change_set['Title'])) {
$changed_fields[] = "title";
}

if (isset($change_set['Country'])) {
$changed_fields[] = "country";
}
if (isset($change_set['AvailableForBureau'])) {
$changed_fields[] = "available_for_bureau";
}
if (isset($change_set['FundedTravel'])) {
$changed_fields[] = "funded_travel";
}
if (isset($change_set['WillingToTravel'])) {
$changed_fields[] = "willing_to_travel";
}
if (isset($change_set['WillingToPresentVideo'])) {
$changed_fields[] = "willing_to_present_video";
}

$fields_str = !empty($changed_fields) ? implode(', ', $changed_fields) : 'properties';
return sprintf(
"Speaker '%s' (%s) updated (%s changed) by user %s",
$full_name,
$speaker_id,
$fields_str,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Speaker '%s' (%s) with email '%s' was deleted by user %s",
$full_name,
$speaker_id,
$email,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("PresentationSpeakerAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace App\Audit\ConcreteFormatters;

/**
* Copyright 2025 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

use App\Audit\AbstractAuditLogFormatter;
use App\Audit\Interfaces\IAuditStrategy;
use models\summit\Presentation;
use Illuminate\Support\Facades\Log;

class PresentationSubmissionAuditLogFormatter extends AbstractAuditLogFormatter
{
private string $event_type;

public function __construct(string $event_type)
{
$this->event_type = $event_type;
}

public function format($subject, array $change_set): ?string
{
if (!$subject instanceof Presentation) {
return null;
}

try {
$title = $subject->getTitle() ?? 'Unknown Presentation';
$id = $subject->getId() ?? 'unknown';
$creator = $subject->getCreator();
$creator_name = $creator ? sprintf("%s %s", $creator->getFirstName() ?? '', $creator->getLastName() ?? '') : 'Unknown';
$creator_name = trim($creator_name) ?: 'Unknown';
$category = $subject->getCategory();
$category_name = $category ? $category->getTitle() : 'Unassigned Track';
$selection_plan = $subject->getSelectionPlan();
$plan_name = $selection_plan ? $selection_plan->getName() : 'Unknown Plan';

switch ($this->event_type) {
case IAuditStrategy::EVENT_ENTITY_CREATION:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrestejerina97 this logic is not quite rite , a presentation could be created from show admin itself
in order to apply this strategy u need to check that endpoint being called is
POST api/v1/summits/{id}/presentations

return sprintf(
"Presentation '%s' (%d) submitted by '%s' to track '%s' (Plan: %s) by user %s",
$title,
$id,
$creator_name,
$category_name,
$plan_name,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$changed_fields = [];
$old_status = null;
$new_status = null;

if (isset($change_set['Title'])) {
$changed_fields[] = "title";
}
if (isset($change_set['Abstract'])) {
$changed_fields[] = "abstract";
}
if (isset($change_set['ProblemAddressed'])) {
$changed_fields[] = "problem_addressed";
}
if (isset($change_set['AttendeesExpectedLearnt'])) {
$changed_fields[] = "attendees_expected_learnt";
}

if (isset($change_set['Status'])) {
$changed_fields[] = "status";
$old_status = $change_set['Status'][0] ?? null;
$new_status = $change_set['Status'][1] ?? null;
}
if (isset($change_set['CategoryID']) || isset($change_set['category'])) {
$changed_fields[] = "track";
}
if (isset($change_set['Published'])) {
$changed_fields[] = "published";
}
if (isset($change_set['SelectionPlanID'])) {
$changed_fields[] = "selection_plan";
}

$fields_str = !empty($changed_fields) ? implode(', ', $changed_fields) : 'properties';

if ($old_status && $new_status) {
return sprintf(
"Presentation '%s' (%d) status changed: %s → %s (%s changed) by user %s",
$title,
$id,
strtoupper($old_status),
strtoupper($new_status),
$fields_str,
$this->getUserInfo()
);
}

return sprintf(
"Presentation '%s' (%d) updated (%s changed) by user %s",
$title,
$id,
$fields_str,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Presentation '%s' (%d) submitted by '%s' to track '%s' was deleted by user %s",
$title,
$id,
$creator_name,
$category_name,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("PresentationSubmissionAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
Loading