Giter Site home page Giter Site logo

Comments (4)

wjstraver avatar wjstraver commented on July 17, 2024 1

Hi Javier,

First off, I needed it fixes, so no better way then deep diving into it myself ;-). I've been able to fix it with our encryptable field by changing the setAttribute() function a bit:

function setAttribute($key, $value)
    {
        if (Str::contains($key, '->')) {
            [$key, $path] = explode('->', $key, 2);
        }

        if (!in_array($key, $this->getEncryptableFields())) {
            return parent::setAttribute($key, $value);
        }

        if (isset($path)) {
            $value = array_merge(
                $this->{$key} ?? [],
                ["$path" => $value]
            );
        }

        $value = isset($value) ? encrypt($value) : null;

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

This way nested values will be set correctly, while still be able to have literal null on encrypted field instead of an encrypted version of null. Only limit our trait now has for array values is "deep nesting", The explode limit of 2 will prevent setting a value like $user->info['extra']['data'] with the arrow notation $user->{"info->extra->data"} = 'something. For our usecase not a problem, but for others might be an issue.

Anyway, I'll see if I find the time to completely test setting nested values without our encryptable trait, since I had some weird behaviour with that as well.

If I don't find anything, I'll close this issue, otherwise I'll keep you all up to date!

from nova-fields.

wjstraver avatar wjstraver commented on July 17, 2024

ok, after some more investigation I don't really know if the bug is with this package, or with Laravel itself or with Nova:

The problem seems to be the way the attributes are being converted in this package while storing. In short it looks something like this:

$this->model->{ $attribute . '->' . $field->attribute} = $value;

When value is null, instead of setting that sub attribute as null, it stores the whole attribute as null.

I can reproduce it here in tinker as well:

>>> $i = ReplyLive\Models\Invitee::find(8037)
=> ReplyLive\Models\Invitee {#4736
     id: 8037,
     info: ""eyJpdiI6InNPZ0IxUlFVMFBtekJMZzNlUjdjUUE9PSIsInZhbHVlIjoiUDd0KzB6MFZmR1JsSW0zY3RsZ0hWOTkxY25obUNsdVVqRHNJU2R3RjVubThpLzJoUUhZNTRpUWxPV1RrU3JwRTcyMmtOQ3NqSzhpNmYwRkk2cVVuREVQTWE4Q0M4SGtqNXgwSzFiLzZhYWV2ZVM3UVhzcmFrbTRPWkdaTkordEVTalBFOFFjdXRjV3lCMVdEVmpxZFFqYnBuaVBoMHQvckhnVkpkNWpibm9nODBXckVEUG0vYWNUdXB6a1FVbVh5ZUVMcSt5aFUrbVRCZmtyWjcwTldiZz09IiwibWFjIjoiZjZmZmQwZGEwNzFiMjZkMDJkMGYyNWExNzE0NGMxMjY4ZjZhZTBjYjQ3NTJjM2RlYTQ0MGE1NjNjZTNjMjY1ZSJ9"",
   }
>>> $i->info
=> [
     "function" => "aa",
     "gender" => "female",
     "diet" => [
       "vegetarian",
     ],
     "newsletter" => "yes",
     "company" => "ffasd",
   ]
>>> $i->{"info->newsletter"} = "no"
=> "no"
>>> $i->info
=> [
     "function" => "aa",
     "gender" => "female",
     "diet" => [
       "vegetarian",
     ],
     "newsletter" => "no",
     "company" => "ffasd",
   ]
>>> $i->{"info->newsletter"} = null
=> null
>>> $i->info
=> null

Also weird: as you can see I've the info field encrypted. If I take the encryption off of this field, the arrow notation for setting the sub attribute does not work at all:

>>> $i = ReplyLive\Models\Invitee::withTrashed()->find(8037)
=> ReplyLive\Models\Invitee {#4734
     id: 8037,
     info: "{"value":"something"}",
   }
>>> $i->info
=> [
     "value" => "something",
   ]
>>> $i->{"info->value"} = "something else"
=> "something else"
>>> $i->info
=> "something else"

Field is casted as array by the way. casting as json seems to give the same result

from nova-fields.

wjstraver avatar wjstraver commented on July 17, 2024

Ok, 1 night of sleep later and I've found something in our Encryptable trait we use on our models, which breaks this.

<?php

namespace ReplyLive\Traits;

use Illuminate\Support\Str;

trait Encryptable
{
    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();

        foreach ($this->getEncryptableFields() as $key) {
            if (array_key_exists($key, $attributes) && isset($attributes[$key])) {
                $attributes[$key] = decrypt($attributes[$key]);
            }
        }

        return $attributes;
    }

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

        if (in_array($key, $this->getEncryptableFields()) && isset($value)) {
            try {
                $value = decrypt($value);
            } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
                return $value;
            }
        }
        return $value;
    }

    public function setAttribute($key, $value)
    {
        if (Str::contains($key, '->')) {
            [$key, $path] = explode('->', $key, 2);
        }

        if (in_array($key, $this->getEncryptableFields()) && isset($value)) {
            if (isset($path)) {
                $value = array_merge(
                    $this->{$key} ?? [],
                    ["$path" => $value]
                );
            }

            $value = encrypt($value);
        }

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

    public function getEncryptableFields(): array
    {
        return property_exists($this, 'encryptable') ? $this->encryptable : [];
    }
}

On line 42 the check isset($value) returns false when $value === null, therefore encryption is not being used and the whole field is set to null.

This is more a blog on fixing my own stuff now than having an actual bug in this package, but I'll keep you up to date with my progress. Also, still doesn't explain why code also breaks when I've had encryption disabled for the given field.....

from nova-fields.

beliolfa avatar beliolfa commented on July 17, 2024

Thank you so much for all your time. We will keep an eye on this issue and see if we can help with anything

from nova-fields.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.