-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathEncryptingModelTrait.php
302 lines (270 loc) · 6.93 KB
/
EncryptingModelTrait.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
<?php
namespace Esensi\Model\Traits;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Encryption\Encrypter;
use Illuminate\Support\Facades\Crypt;
/**
* Trait that implements the Encrypting Model Interface.
*
*/
trait EncryptingModelTrait
{
/**
* Whether the model is encrypting or not.
*
* @var bool
*/
protected $encrypting = true;
/**
* The Encrypter to use for encryption.
*
* @var Illuminate\Encryption\Encrypter
*/
protected $encryptor;
/**
* Dynamically retrieve attributes.
*
* @param string $key
*
* @return mixed
*/
public function __get($key)
{
// Dynamically retrieve the encrypted attribute
$value = $this->getDynamicEncrypted($key);
if (! is_null($value) || is_string($value)) {
return $value;
}
// Default Eloquent dynamic getter
return parent::__get($key);
}
/**
* Dynamically set attributes.
*
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
// Dynamically set the encryptable attribute
if (! empty($value) && $this->setDynamicEncryptable($key, $value)) {
return;
}
// Default Eloquent dynamic setter
return parent::__set($key, $value);
}
/**
* Get an encrypted attribute dynamically.
*
* @param string $attribute
* @return mixed
*/
protected function getDynamicEncrypted($attribute)
{
// Dynamically get the encrypted attributes
if ($this->isEncryptable($attribute)) {
// Decrypt only encrypted values
if ($this->isEncrypted($attribute)) {
return $this->getEncryptedAttribute($attribute);
}
}
}
/**
* Set an encryptable attribute dynamically.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
protected function setDynamicEncryptable($attribute, $value)
{
// Dynamically set the encryptable attribute
if ($this->isEncryptable($attribute)) {
// Encrypt only decrypted values
if ($this->isDecrypted($attribute)) {
$this->setEncryptingAttribute($attribute, $value);
return true;
}
}
return false;
}
/**
* Get the encryptable attributes.
*
* @return array
*/
public function getEncryptable()
{
return $this->encryptable ?: [];
}
/**
* Set the encryptable attributes.
*
* @param array $attributes to encrypt
*/
public function setEncryptable(array $attributes)
{
$this->encryptable = $attributes;
}
/**
* Add an attribute to the encryptable array.
*
* @example addEncryptable( string $attribute, ... )
*
* @param string $attribute to purge
*/
public function addEncryptable($attribute)
{
$this->mergeEncryptable(func_get_args());
}
/**
* Remove an attribute from the encryptable array.
*
* @example addEncryptable( string $attribute, ... )
*
* @param string $attribute to purge
*/
public function removeEncryptable($attribute)
{
$this->encryptable = array_diff($this->encryptable, func_get_args());
}
/**
* Merge an array of attributes with the encryptable array.
*
* @param array $attributes to purge
*/
public function mergeEncryptable(array $attributes)
{
$this->encryptable = array_merge($this->encryptable, $attributes);
}
/**
* Returns whether or not the model will encrypt
* attributes when setting and decrypt when getting.
*
* @return bool
*/
public function getEncrypting()
{
return $this->encrypting;
}
/**
* Set whether or not the model will encrypt attributes
* when setting and decrypt when getting.
*
* @param bool
*/
public function setEncrypting($value)
{
$this->encrypting = (bool) $value;
}
/**
* Set the Encrypter to use for encryption.
*
* @return Illuminate\Encryption\Encrypter
*/
public function getEncrypter()
{
return $this->encryptor ?: Crypt::getFacadeRoot();
}
/**
* Set the Encrypter to use for encryption.
*
* @param Illuminate\Encryption\Encrypter $encryptor
*/
public function setEncrypter(Encrypter $encryptor)
{
$this->encryptor = $encryptor;
}
/**
* Returns whether the attribute is encryptable.
*
* @param string $attribute name
* @return bool
*/
public function isEncryptable($attribute)
{
return $this->getEncrypting()
&& in_array($attribute, $this->getEncryptable());
}
/**
* Returns whether the attribute is encrypted.
*
* @param string $attribute name
* @return bool
*/
public function isEncrypted($attribute)
{
if (! array_key_exists($attribute, $this->attributes)) {
return false;
}
try {
$this->decrypt(array_get($this->attributes, $attribute));
} catch (DecryptException $exception) {
return false;
}
return true;
}
/**
* Returns whether the attribute is decrypted.
*
* @param string $attribute name
* @return bool
*/
public function isDecrypted($attribute)
{
return ! $this->isEncrypted($attribute);
}
/**
* Encrypt attributes that should be encrypted.
*/
public function encryptAttributes()
{
foreach ($this->getEncryptable() as $attribute) {
$this->setEncryptingAttribute($attribute, array_get($this->attributes, $attribute));
}
}
/**
* Return an encrypted string for the value.
*
* @param string $value
* @return string
*/
public function encrypt($value)
{
return $this->getEncrypter()
->encrypt($value);
}
/**
* Return a decrypted string for the value.
*
* @param string $value
* @return string
*/
public function decrypt($value)
{
return $this->getEncrypter()
->decrypt($value);
}
/**
* Get the decrypted value for an encrypted attribute.
*
* @param string $attribute name
* @return string
*/
public function getEncryptedAttribute($attribute)
{
$value = array_get($this->attributes, $attribute);
return $this->isEncrypted($attribute) ? $this->decrypt($value) : $value;
}
/**
* Set an encrypted value for an encryptable attribute.
*
* @param string $attribute name
* @param string $value to encrypt
*/
public function setEncryptingAttribute($attribute, $value)
{
array_set($this->attributes, $attribute, $this->encrypt($value));
}
}