Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
7 changes: 5 additions & 2 deletions app/Audit/AbstractAuditLogFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

abstract class AbstractAuditLogFormatter implements IAuditLogFormatter
{
protected AuditContext $ctx;
protected ?AuditContext $ctx = null;
protected string $event_type;

public function __construct(string $event_type)
Expand All @@ -34,6 +34,9 @@ final public function setContext(AuditContext $ctx): void

protected function getUserInfo(): string
{
if (app()->runningInConsole()) {
return 'Worker Job';
}
if (!$this->ctx) {
return 'Unknown (unknown)';
}
Expand Down Expand Up @@ -126,5 +129,5 @@ protected function formatFieldChange(string $prop_name, $old_value, $new_value):
return sprintf("Property \"%s\" has changed from \"%s\" to \"%s\"", $prop_name, $old_display, $new_display);
}

abstract public function format($subject, array $change_set): ?string;
abstract public function format(mixed $subject, array $change_set): ?string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace App\Audit\ConcreteFormatters\ChildEntityFormatters;

/**
* 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 models\summit\RSVPAnswer;

class RSVPAnswerAuditLogFormatter implements IChildEntityAuditLogFormatter
{
public function format($subject, string $child_entity_action_type, ?string $additional_info = ""): ?string
{
if (!$subject instanceof RSVPAnswer) {
return null;
}

try {
$questionId = $subject->getQuestionId();
$value = $subject->getValue();
$question = $subject->getQuestion();
$questionLabel = $question?->getLabel() ?? sprintf("Question #%d", $questionId);

switch ($child_entity_action_type) {
case IChildEntityAuditLogFormatter::CHILD_ENTITY_CREATION:
return sprintf(
"RSVP Answer added for question '%s' with value '%s'",
$questionLabel,
$value
);

case IChildEntityAuditLogFormatter::CHILD_ENTITY_UPDATE:
if (!empty($additional_info)) {
return sprintf(
"RSVP Answer for question '%s' updated: %s",
$questionLabel,
$additional_info
);
}
return sprintf(
"RSVP Answer for question '%s' updated to '%s'",
$questionLabel,
$value
);

case IChildEntityAuditLogFormatter::CHILD_ENTITY_DELETION:
return sprintf(
"RSVP Answer removed for question '%s' (had value '%s')",
$questionLabel,
$value
);
}
} catch (\Exception $ex) {
return null;
}

return null;
}
}
76 changes: 76 additions & 0 deletions app/Audit/ConcreteFormatters/CompanyAuditLogFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?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\main\Company;
use Illuminate\Support\Facades\Log;

class CompanyAuditLogFormatter extends AbstractAuditLogFormatter
{
Comment thread
smarcet marked this conversation as resolved.
public function format($subject, array $change_set): ?string
{
if (!$subject instanceof Company) {
return null;
}

try {
$name = $subject->getName() ?? 'Unknown Company';
$id = $subject->getId() ?? 'unknown';
$city = $subject->getCity() ?? 'N/A';
$country = $subject->getCountry() ?? 'N/A';
$display_on_site = $subject->isDisplayOnSite() ? 'yes' : 'no';

switch ($this->event_type) {
case IAuditStrategy::EVENT_ENTITY_CREATION:
return sprintf(
"Company '%s' (%d) created located in %s, %s, display on site: %s by user %s",
$name,
$id,
$city,
$country,
$display_on_site,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$change_details = $this->buildChangeDetails($change_set);
return sprintf(
"Company '%s' (%d) updated: %s by user %s",
$name,
$id,
$change_details,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Company '%s' (%d) located in %s, %s was deleted by user %s",
$name,
$id,
$city,
$country,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("CompanyAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
11 changes: 10 additions & 1 deletion app/Audit/ConcreteFormatters/EntityCreationAuditLogFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
*/
class EntityCreationAuditLogFormatter extends AbstractAuditLogFormatter
{
public function __construct()
{
parent::__construct('entity_creation');
Copy link
Copy Markdown
Collaborator

@smarcet smarcet Jan 7, 2026

Choose a reason for hiding this comment

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

@andrestejerina97 what is the purpoise of this hardcoded string?
we should be using here only constants defined here
at

interface IAuditStrategy

}

protected function getCreationIgnoredEntities(): array {
return [
'PresentationAction',
Expand All @@ -39,6 +44,10 @@ public function format($subject, $change_set): ?string {
$class_name = (new ReflectionClass($subject))->getShortName();
$ignored_entities = $this->getCreationIgnoredEntities();
if (in_array($class_name, $ignored_entities)) return null;
return "{$class_name} created";

$entity_id = method_exists($subject, 'getId') ? $subject->getId() : 'N/A';
$user_info = $this->getUserInfo();

return "{$class_name} (ID: {$entity_id}) created by {$user_info}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ class EntityDeletionAuditLogFormatter extends AbstractAuditLogFormatter
*/
private $child_entity_formatter;

public function __construct(?IChildEntityAuditLogFormatter $child_entity_formatter)
public function __construct(?IChildEntityAuditLogFormatter $child_entity_formatter = null)
{
parent::__construct('entity_deletion');
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

$this->child_entity_formatter = $child_entity_formatter;
}

Expand All @@ -56,6 +57,8 @@ public function format($subject, $change_set): ?string {
->format($subject, IChildEntityAuditLogFormatter::CHILD_ENTITY_DELETION);
}

return "{$class_name} deleted";
$entity_id = method_exists($subject, 'getId') ? $subject->getId() : 'unknown';
$user_info = $this->getUserInfo();
return "{$class_name} (ID: {$entity_id}) deleted by {$user_info}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ class EntityUpdateAuditLogFormatter extends AbstractAuditLogFormatter
*/
private $child_entity_formatter;

public function __construct(?IChildEntityAuditLogFormatter $child_entity_formatter)
public function __construct(?IChildEntityAuditLogFormatter $child_entity_formatter = null)
{
parent::__construct('entity_update');
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

$this->child_entity_formatter = $child_entity_formatter;
}

Expand Down Expand Up @@ -157,6 +158,10 @@ public function format($subject, $change_set): ?string

if (count($res) == 0) return null;

return join("|", $res);
$entity_id = method_exists($subject, 'getId') ? $subject->getId() : 'N/A';
$user_info = $this->getUserInfo();
$message = join("|", $res);

return "{$class_name} (ID: {$entity_id}) updated by {$user_info}: {$message}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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\PresentationCategory;
use Illuminate\Support\Facades\Log;

class PresentationCategoryAuditLogFormatter extends AbstractAuditLogFormatter
{
Comment thread
smarcet marked this conversation as resolved.
public function format($subject, array $change_set): ?string
{
if (!$subject instanceof PresentationCategory) {
return null;
}

try {
$title = $subject->getTitle() ?? 'Unknown Category';
$code = $subject->getCode() ?? 'N/A';
$id = $subject->getId() ?? 'unknown';
$summit = $subject->getSummit();
$summit_name = $summit ? ($summit->getName() ?? 'Unknown Summit') : 'Unknown Summit';

switch ($this->event_type) {
case IAuditStrategy::EVENT_ENTITY_CREATION:
return sprintf(
"Presentation Category '%s' (%s) (%d) created for Summit '%s' by user %s",
$title,
$code,
$id,
$summit_name,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$change_details = $this->buildChangeDetails($change_set);
return sprintf(
"Presentation Category '%s' (%s) (%d) for Summit '%s' updated: %s by user %s",
$title,
$code,
$id,
$summit_name,
$change_details,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Presentation Category '%s' (%s) (%d) for Summit '%s' was deleted by user %s",
$title,
$code,
$id,
$summit_name,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("PresentationCategoryAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?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\PresentationCategoryGroup;
use Illuminate\Support\Facades\Log;

class PresentationCategoryGroupAuditLogFormatter extends AbstractAuditLogFormatter
{
Comment thread
smarcet marked this conversation as resolved.
public function format($subject, array $change_set): ?string
{
if (!$subject instanceof PresentationCategoryGroup) {
return null;
}

try {
$name = $subject->getName() ?? 'Unknown Track Group';
$id = $subject->getId() ?? 'unknown';
$summit = $subject->getSummit();
$summit_name = $summit ? ($summit->getName() ?? 'Unknown Summit') : 'Unknown Summit';
$color = $subject->getColor() ?? 'N/A';

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

return sprintf(
"Track Group (PresentationCategoryGroup) '%s' (%d) created for Summit '%s' with color '%s', max votes: %d by user %s",
$name,
$id,
$summit_name,
$color,
$subject->getMaxAttendeeVotes(),
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_UPDATE:
$change_details = $this->buildChangeDetails($change_set);
return sprintf(
"Track Group (PresentationCategoryGroup) '%s' (%d) for Summit '%s' updated: %s by user %s",
$name,
$id,
$summit_name,
$change_details,
$this->getUserInfo()
);

case IAuditStrategy::EVENT_ENTITY_DELETION:
return sprintf(
"Track Group (PresentationCategoryGroup) '%s' (%d) for Summit '%s' with color '%s' was deleted by user %s",
$name,
$id,
$summit_name,
$color,
$this->getUserInfo()
);
}
} catch (\Exception $ex) {
Log::warning("PresentationCategoryGroupAuditLogFormatter error: " . $ex->getMessage());
}

return null;
}
}
Loading