Issues (15)

src/DecryptModel.php (4 issues)

1
<?php
2
3
namespace Magros\Encryptable;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Schema\Blueprint;
8
use Illuminate\Support\Facades\Schema;
9
use Illuminate\Support\Facades\DB;
10
11
class DecryptModel extends Command
12
{
13
    /**
14
     * The name and signature of the console command.
15
     *
16
     * @var string
17
     */
18
    protected $signature = 'encryptable:decryptModel {model}';
19
20
    /**
21
     * The console command description.
22
     *
23
     * @var string
24
     */
25
    protected $description = 'Encrypt models rows';
26
27
    private $attributes = [];
28
    private $model;
29
30
    /**
31
     * Execute the console command.
32
     *
33
     * @return mixed
34
     * @throws \Exception
35
     */
36
    public function handle()
37
    {
38
        $class = $this->argument('model');
39
        $this->model = $this->guardClass($class);
40
        $this->attributes = $this->model->getEncryptableAttributes();
41
        $table = $this->model->getTable();
42
        $total = $this->model->where('encrypted', 1)->count();
43
        $this->model::$enableEncryption = false;
44
45
        if($total > 0){
46
            $this->comment($total.' records will be decrypted');
0 ignored issues
show
Are you sure $total of type Illuminate\Database\Eloquent\Builder|integer|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
            $this->comment(/** @scrutinizer ignore-type */ $total.' records will be decrypted');
Loading history...
47
            $bar = $this->output->createProgressBar($total);
0 ignored issues
show
It seems like $total can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $max of Symfony\Component\Consol...le::createProgressBar() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

47
            $bar = $this->output->createProgressBar(/** @scrutinizer ignore-type */ $total);
Loading history...
48
            $bar->setFormat('%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%');
49
50
            $records =  $this->model->orderBy('id', 'asc')->where('encrypted', 1)->get();
51
            foreach ($records as $record) {
52
                $record->timestamps = false;
53
                $attributes = $this->getDecryptedAttributes($record);
54
                DB::table($table)->where('id', $record->id)->update($attributes);
55
                $bar->advance();
56
                $record = null;
0 ignored issues
show
The assignment to $record is dead and can be removed.
Loading history...
57
                $attributes = null;
0 ignored issues
show
The assignment to $attributes is dead and can be removed.
Loading history...
58
            }
59
            $bar->finish();
60
        }
61
62
        $this->comment('Finished encryption');
63
    }
64
65
    private function getDecryptedAttributes($record)
66
    {
67
        $encryptedFields = ['encrypted' => 0 ];
68
69
        foreach ($this->attributes as $attribute) {
70
            $raw = $record->{$attribute};
71
72
            if (str_contains($raw, $record->encrypter()->getPrefix())) {
73
74
                $encryptedFields[$attribute] = $this->model->decryptAttribute($raw);
75
            }
76
        }
77
        return $encryptedFields;
78
    }
79
80
    private function validateHasEncryptedColumn($model)
81
    {
82
        $table = $model->getTable();
83
        if (! Schema::hasColumn($table, 'encrypted')) {
84
            $this->comment('Creating encrypted column');
85
            Schema::table($table, function (Blueprint $table) {
86
                $table->tinyInteger('encrypted')->default(0);
87
            });
88
        }
89
    }
90
91
    /**
92
     * @param $class
93
     * @return Model
94
     * @throws \Exception
95
     */
96
    public function guardClass($class)
97
    {
98
        if (!class_exists($class))
99
            throw new \Exception("Class {$class} does not exists");
100
        $model = new $class();
101
        $this->validateHasEncryptedColumn($model);
102
        return $model;
103
    }
104
}
105