Laravel-activitylog: Logging Encrypted Attributes Or Prevent Logging Under Conditions

Created on 16 May 2019  路  6Comments  路  Source: spatie/laravel-activitylog

Hello.

First of all, congrats on your work, I use this package (and others by you) in almost all my projects.

In a current project I am working on, I have 2 requirements. One is that the data must be encrypted in the database and the other that it should log every change in the models.

So, I created a trait that encrypts/decrypts properties in the model

trait Encryptable
{
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) {
            $value = decrypt($value);
        }

        return $value;
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }
}

Next, I added the LogsActivity trait in my model and I realised I have 2 major issues.

The first is that the activity is saved with the encrypted values (this could be solved in the views I think) and the other is that, since the encryption is changed each time, even if no change is made to that data I still get an activity logged (because it compares encrypted values).

I tried to tackle this with the tapActivity function and I am stuck at the last step (preventing the activity from being saved if the properties are empty).

public function tapActivity(Activity $activity, string $eventName)
    {
        if (property_exists($this, 'encryptable'))
        {
            $properties = $activity->properties->toArray();
            $changes = $activity->changes()->toArray();

            foreach (Arr::get($changes, 'attributes') as $attribute_name => $attribute_value)
            {
                if (in_array($attribute_name, $this->encryptable)) {
                    $attribute_value = decrypt($attribute_value);

                    if (decrypt($changes['old'][$attribute_name]) == $attribute_value)
                    {
                        Arr::forget($properties, ['attributes.' . $attribute_name, 'old.' . $attribute_name]);
                    }
                }
            }

            $activity->properties = $activity->properties->merge(collect($properties));
        }
    }

What I want is to prevent the save if the activity has no properties. Is this possible;

bug

All 6 comments

Hey,

thanks for the flowers.

I've added an unittest for your scenario and it passes #534 until I change the specific accessor/mutator into, your case, general ones.
I think that this is related to \Spatie\Activitylog\Traits\DetectsChanges::logChanges(). I will try to debug it deeper and find a way to also respect the general accessor/mutator.

So, I've fixed the logChanges() method to use the getter in general, The toArray() method doesn't call getters - this was the problem.

@achatzi78 could you check if the dev-issue-532 version solves your problem?

Wow! I only expected a pointer or a suggestion, not a complete solution.

It works and it solves both my issues. Thank you very much for your efforts!

Kudos!

Ok, I would like to wait for review by @freekmurze of the last open PRs. I hope that he will have time tomorrow. Otherwise I will release it my own at monday.
https://github.com/spatie/laravel-activitylog/labels/next%20release

I do not mind waiting for the release, I still have time until deployment.

Thank you again.

Was this page helpful?
0 / 5 - 0 ratings