| 
									
										
										
										
											2021-07-03 03:53:33 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Access\Mfa; | 
					
						
							| 
									
										
										
										
											2021-07-03 03:53:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use Illuminate\Support\Str; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BackupCodeService | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Generate a new set of 16 backup codes. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function generateNewSet(): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $codes = []; | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |         while (count($codes) < 16) { | 
					
						
							| 
									
										
										
										
											2021-07-03 03:53:33 +08:00
										 |  |  |             $code = Str::random(5) . '-' . Str::random(5); | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |             if (!in_array($code, $codes)) { | 
					
						
							|  |  |  |                 $codes[] = strtolower($code); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-03 03:53:33 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-03 03:53:33 +08:00
										 |  |  |         return $codes; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if the given code matches one of the available options. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function inputCodeExistsInSet(string $code, string $codeSet): bool | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $cleanCode = $this->cleanInputCode($code); | 
					
						
							|  |  |  |         $codes = json_decode($codeSet); | 
					
						
							| 
									
										
										
										
											2021-08-21 22:49:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |         return in_array($cleanCode, $codes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove the given input code from the given available options. | 
					
						
							| 
									
										
										
										
											2021-08-21 22:38:43 +08:00
										 |  |  |      * Will return a JSON string containing the codes. | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-08-21 22:38:43 +08:00
										 |  |  |     public function removeInputCodeFromSet(string $code, string $codeSet): string | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $cleanCode = $this->cleanInputCode($code); | 
					
						
							|  |  |  |         $codes = json_decode($codeSet); | 
					
						
							|  |  |  |         $pos = array_search($cleanCode, $codes, true); | 
					
						
							|  |  |  |         array_splice($codes, $pos, 1); | 
					
						
							| 
									
										
										
										
											2021-08-21 22:49:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-02 23:35:37 +08:00
										 |  |  |         return json_encode($codes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Count the number of codes in the given set. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function countCodesInSet(string $codeSet): int | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return count(json_decode($codeSet)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function cleanInputCode(string $code): string | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return strtolower(str_replace(' ', '-', trim($code))); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-21 22:49:40 +08:00
										 |  |  | } |