1313use Exception ;
1414
1515/**
16- * Sync Class CrmController
17- * Example: (new CrmController())->setModel($user)->execute();
16+ * DB Encrypt / Decrypt Controller
1817 *
1918 * @package Wazza\DbEncrypt\Http\Controllers
2019 * @version 1.0.0
21- * @todo convert the log class to be injected into the controller instead of using the facade
2220 */
2321
24- class DnEncryptController extends BaseController
22+ class DbEncryptController extends BaseController
2523{
2624 /**
2725 * The model to sync
@@ -93,6 +91,16 @@ public function setModel(?Model $model = null)
9391 */
9492 public function setEncryptedProperties (array $ propertyMapping = []): self
9593 {
94+ // Check for conflicts: encrypted property must not exist as a column in the model's table
95+ $ table = $ this ->model ? $ this ->model ->getTable () : null ;
96+ $ schema = $ this ->model ? $ this ->model ->getConnection ()->getSchemaBuilder () : null ;
97+ if ($ table && $ schema ) {
98+ foreach ($ propertyMapping as $ prop ) {
99+ if ($ schema ->hasColumn ($ table , $ prop )) {
100+ throw new Exception ("Cannot specify encrypted property ' {$ prop }' because it already exists as a column in the model's table ' {$ table }'. " );
101+ }
102+ }
103+ }
96104 // set the property mappings
97105 $ this ->encryptedProperties = $ propertyMapping ;
98106 $ this ->logger ->infoLow ('DB Encrypt Mapping: ` ' . json_encode ($ this ->encryptedProperties ) . '` ' );
@@ -133,42 +141,82 @@ public function isModelDefined(): bool
133141 }
134142
135143 /**
136- * Encrypt all of the model defined ($this->encryptedProperties) properties .
137- * If $property is provided, only that property will be encrypted.
144+ * Encrypt all properties of the model.
145+ * This method will encrypt all properties defined in the model's encrypted properties .
138146 *
139- * @param mixed $property The property to encrypt. If null, all properties will be encrypted.
140147 * @return void
141148 * @throws Exception
142149 */
143- public function encrypt ( $ property = null )
150+ public function encryptAll ( )
144151 {
145152 // check if the model is set
146153 if (!$ this ->isModelDefined ()) {
147154 throw new Exception ('Model is not set. Please set the model using the `setModel` method. ' );
148155 }
149156
150- // check if the property is set
151- if ($ property !== null && !in_array ($ property , $ this ->encryptedProperties )) {
152- throw new Exception ('Property ` ' . $ property . '` is not defined in the encrypted properties. ' );
157+ // encrypt all properties
158+ $ this ->encrypt ();
159+ }
160+
161+ /**
162+ * Encrypt a specific property of the model.
163+ * This method will only encrypt the property if it is defined in the model's encrypted properties.
164+ *
165+ * @param string $property
166+ * @return void
167+ * @throws Exception
168+ */
169+ public function encryptProperty (string $ property )
170+ {
171+ // check if the model is set
172+ if (!$ this ->isModelDefined ()) {
173+ throw new Exception ('Model is not set. Please set the model using the `setModel` method. ' );
153174 }
154175
155- // encrypt the properties
156- $ this ->logger ->infoLow ('Encrypting properties for model: ' . get_class ($ this ->model ) . ', property: ' . ($ property ?? 'all ' ));
176+ // encrypt the property
177+ $ this ->encrypt ($ property );
178+ }
157179
158- // loop through the encrypted properties
180+ /**
181+ * Encrypt all of the model defined ($this->encryptedProperties) properties.
182+ * If $property is provided, only that property will be encrypted.
183+ *
184+ * @param mixed $property The property to encrypt. If null, all properties will be encrypted.
185+ * @return void
186+ * @throws Exception
187+ */
188+ public function encrypt (
189+ $ property = null
190+ ) {
191+ if (!$ this ->isModelDefined ()) {
192+ throw new Exception ('Model is not set. Please set the model using the `setModel` method. ' );
193+ }
194+ if ($ property !== null && !in_array ($ property , $ this ->encryptedProperties , true )) {
195+ throw new Exception ('Property ` ' . $ property . '` is not defined in the encrypted properties. ' );
196+ }
197+ $ this ->logger ->infoLow ('Encrypting properties for model: ' . $ this ->model ->getTable () . ', property: ' . ($ property ?? 'all ' ));
159198 foreach ($ this ->encryptedProperties as $ prop ) {
160- // making sure the provided property to encrypt (if any) is defined in the model encrypted properties list
161199 if ($ property === null || $ prop === $ property ) {
162- // check if the property exists in the model
163- if (property_exists ($ this ->model , $ prop )) {
164- // encrypt the property
200+ if (array_key_exists ($ prop , $ this ->model ->getAttributes ())) {
201+ // Use Eloquent attribute check
165202 $ value = $ this ->model ->{$ prop };
166- $ encryptedValue = Encryptor::encrypt ($ value );
203+ if ($ value === null || $ value === '' ) {
204+ // if the value was encrypted, hard delete it form the encrypted_attributes table
205+ EncryptedAttributes::where ([
206+ 'object_type ' => $ this ->model ->getTable (),
207+ 'object_id ' => $ this ->model ->getKey (),
208+ 'attribute ' => $ prop ,
209+ ])->delete ();
167210
168- // save the encrypted value in the EncryptedAttributes model
211+ // done
212+ continue ;
213+ }
214+
215+ // Encrypt the value and store it in the encrypted_attributes table
216+ $ encryptedValue = Encryptor::encrypt ($ value );
169217 EncryptedAttributes::updateOrCreate (
170218 [
171- 'object_type ' => get_class ( $ this ->model ),
219+ 'object_type ' => $ this ->model -> getTable ( ),
172220 'object_id ' => $ this ->model ->getKey (),
173221 'attribute ' => $ prop ,
174222 ],
@@ -178,15 +226,50 @@ public function encrypt($property = null)
178226 ]
179227 );
180228
181- // log the encryption
182- $ this ->logger ->infoLow ('Encrypted property: ' . $ prop . ', value: ' . $ value );
229+ // Do NOT log the actual value
230+ $ this ->logger ->infoLow ('Encrypted property: ' . $ prop . ' [ value hidden for security] ' );
183231 } else {
184- throw new Exception ( ' Property ` ' . $ prop . ' ` does not exist in the model. ' ) ;
232+ continue ;
185233 }
186234 }
187235 }
236+ $ this ->logger ->infoLow ('Encryption completed for model: ' . $ this ->model ->getTable () . ', properties: ' . json_encode ($ this ->encryptedProperties ));
237+ }
188238
189- // log the encryption
190- $ this ->logger ->infoLow ('Encryption completed for model: ' . get_class ($ this ->model ) . ', properties: ' . json_encode ($ this ->encryptedProperties ));
239+ /**
240+ * Decrypt all of the model defined ($this->encryptedProperties) properties.
241+ * If $property is provided, only that property will be decrypted.
242+ *
243+ * @param mixed $property The property to decrypt. If null, all properties will be decrypted.
244+ * @return void
245+ * @throws Exception
246+ */
247+ public function decrypt ($ property = null )
248+ {
249+ if (!$ this ->isModelDefined ()) {
250+ throw new Exception ('Model is not set. Please set the model using the `setModel` method. ' );
251+ }
252+ if ($ property !== null && !in_array ($ property , $ this ->encryptedProperties , true )) {
253+ throw new Exception ('Property ` ' . $ property . '` is not defined in the encrypted properties. ' );
254+ }
255+ $ this ->logger ->infoLow ('Decrypting properties for model: ' . $ this ->model ->getTable () . ', property: ' . ($ property ?? 'all ' ));
256+ foreach ($ this ->encryptedProperties as $ prop ) {
257+ if ($ property === null || $ prop === $ property ) {
258+ $ encryptedAttribute = EncryptedAttributes::where ([
259+ 'object_type ' => $ this ->model ->getTable (),
260+ 'object_id ' => $ this ->model ->getKey (),
261+ 'attribute ' => $ prop ,
262+ ])->first ();
263+ if ($ encryptedAttribute && $ encryptedAttribute ->encrypted_value ) {
264+ $ decryptedValue = Encryptor::decrypt ($ encryptedAttribute ->encrypted_value );
265+ $ this ->model ->{$ prop } = $ decryptedValue ;
266+ $ this ->logger ->infoLow ('Decrypted property: ' . $ prop . ' - success. ' );
267+ } else {
268+ $ this ->model ->{$ prop } = null ;
269+ $ this ->logger ->infoLow ('Decrypted property: ' . $ prop . ' - not found, set to null. ' );
270+ }
271+ }
272+ }
273+ $ this ->logger ->infoLow ('Decryption completed for model: ' . $ this ->model ->getTable () . ', properties: ' . json_encode ($ this ->encryptedProperties ));
191274 }
192275}
0 commit comments