| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Users; | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Access\UserInviteService; | 
					
						
							|  |  |  | use BookStack\Activity\ActivityType; | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  | use BookStack\Entities\EntityProvider; | 
					
						
							| 
									
										
										
										
											2022-02-03 23:12:50 +08:00
										 |  |  | use BookStack\Exceptions\NotifyException; | 
					
						
							| 
									
										
										
										
											2018-12-31 00:11:58 +08:00
										 |  |  | use BookStack\Exceptions\UserUpdateException; | 
					
						
							| 
									
										
										
										
											2022-02-03 23:12:50 +08:00
										 |  |  | use BookStack\Facades\Activity; | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  | use BookStack\Uploads\UserAvatars; | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Users\Models\Role; | 
					
						
							|  |  |  | use BookStack\Users\Models\User; | 
					
						
							| 
									
										
										
										
											2016-09-18 04:33:55 +08:00
										 |  |  | use Exception; | 
					
						
							| 
									
										
										
										
											2022-09-22 23:54:27 +08:00
										 |  |  | use Illuminate\Support\Facades\Hash; | 
					
						
							| 
									
										
										
										
											2021-09-26 22:37:55 +08:00
										 |  |  | use Illuminate\Support\Facades\Log; | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  | use Illuminate\Support\Str; | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class UserRepo | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |     protected UserAvatars $userAvatar; | 
					
						
							|  |  |  |     protected UserInviteService $inviteService; | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * UserRepo constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |     public function __construct(UserAvatars $userAvatar, UserInviteService $inviteService) | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  |         $this->userAvatar = $userAvatar; | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |         $this->inviteService = $inviteService; | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |      * Get a user by their email address. | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |     public function getByEmail(string $email): ?User | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  |         return User::query()->where('email', '=', $email)->first(); | 
					
						
							| 
									
										
										
										
											2015-09-05 00:16:58 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-06 03:25:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  |      * Get a user by their ID. | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  |     public function getById(int $id): User | 
					
						
							| 
									
										
										
										
											2015-09-06 03:25:57 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-09 07:46:38 +08:00
										 |  |  |         return User::query()->findOrFail($id); | 
					
						
							| 
									
										
										
										
											2015-09-06 03:25:57 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-10 07:06:12 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get a user by their slug. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getBySlug(string $slug): User | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return User::query()->where('slug', '=', $slug)->firstOrFail(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |      * Create a new basic instance of user with the given pre-validated data. | 
					
						
							| 
									
										
										
										
											2022-02-08 23:29:58 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |      * @param array{name: string, email: string, password: ?string, external_auth_id: ?string, language: ?string, roles: ?array} $data | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |     public function createWithoutActivity(array $data, bool $emailConfirmed = false): User | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-11 06:37:53 +08:00
										 |  |  |         $user = new User(); | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |         $user->name = $data['name']; | 
					
						
							|  |  |  |         $user->email = $data['email']; | 
					
						
							| 
									
										
										
										
											2022-09-22 23:54:27 +08:00
										 |  |  |         $user->password = Hash::make(empty($data['password']) ? Str::random(32) : $data['password']); | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |         $user->email_confirmed = $emailConfirmed; | 
					
						
							|  |  |  |         $user->external_auth_id = $data['external_auth_id'] ?? ''; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-11 06:37:53 +08:00
										 |  |  |         $user->refreshSlug(); | 
					
						
							|  |  |  |         $user->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |         if (!empty($data['language'])) { | 
					
						
							|  |  |  |             setting()->putUser($user, 'language', $data['language']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($data['roles'])) { | 
					
						
							|  |  |  |             $this->setUserRoles($user, $data['roles']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->downloadAndAssignUserAvatar($user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $user; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * As per "createWithoutActivity" but records a "create" activity. | 
					
						
							| 
									
										
										
										
											2022-02-08 23:29:58 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |      * @param array{name: string, email: string, password: ?string, external_auth_id: ?string, language: ?string, roles: ?array} $data | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function create(array $data, bool $sendInvite = false): User | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-02-04 09:02:13 +08:00
										 |  |  |         $user = $this->createWithoutActivity($data, true); | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($sendInvite) { | 
					
						
							|  |  |  |             $this->inviteService->sendInvitation($user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Activity::add(ActivityType::USER_CREATE, $user); | 
					
						
							| 
									
										
										
										
											2022-02-08 23:29:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-11 06:37:53 +08:00
										 |  |  |         return $user; | 
					
						
							| 
									
										
										
										
											2015-09-06 19:14:32 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-04 00:52:28 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Update the given user with the given data. | 
					
						
							| 
									
										
										
										
											2022-02-08 23:29:58 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-02-04 00:52:28 +08:00
										 |  |  |      * @param array{name: ?string, email: ?string, external_auth_id: ?string, password: ?string, roles: ?array<int>, language: ?string} $data | 
					
						
							| 
									
										
										
										
											2022-02-08 23:29:58 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-02-04 00:52:28 +08:00
										 |  |  |      * @throws UserUpdateException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function update(User $user, array $data, bool $manageUsersAllowed): User | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!empty($data['name'])) { | 
					
						
							|  |  |  |             $user->name = $data['name']; | 
					
						
							|  |  |  |             $user->refreshSlug(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($data['email']) && $manageUsersAllowed) { | 
					
						
							|  |  |  |             $user->email = $data['email']; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($data['external_auth_id']) && $manageUsersAllowed) { | 
					
						
							|  |  |  |             $user->external_auth_id = $data['external_auth_id']; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($data['roles']) && $manageUsersAllowed) { | 
					
						
							|  |  |  |             $this->setUserRoles($user, $data['roles']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($data['password'])) { | 
					
						
							| 
									
										
										
										
											2022-09-22 23:54:27 +08:00
										 |  |  |             $user->password = Hash::make($data['password']); | 
					
						
							| 
									
										
										
										
											2022-02-04 00:52:28 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($data['language'])) { | 
					
						
							|  |  |  |             setting()->putUser($user, 'language', $data['language']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $user->save(); | 
					
						
							|  |  |  |         Activity::add(ActivityType::USER_UPDATE, $user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $user; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Remove the given user from storage, Delete all related content. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2018-01-28 22:08:14 +08:00
										 |  |  |      * @throws Exception | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  |     public function destroy(User $user, ?int $newOwnerId = null) | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-02-03 23:12:50 +08:00
										 |  |  |         $this->ensureDeletable($user); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |         $user->socialAccounts()->delete(); | 
					
						
							| 
									
										
										
										
											2019-12-30 01:03:52 +08:00
										 |  |  |         $user->apiTokens()->delete(); | 
					
						
							| 
									
										
										
										
											2021-05-23 20:41:56 +08:00
										 |  |  |         $user->favourites()->delete(); | 
					
						
							| 
									
										
										
										
											2021-07-01 05:10:02 +08:00
										 |  |  |         $user->mfaValues()->delete(); | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |         $user->delete(); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 22:08:14 +08:00
										 |  |  |         // Delete user profile images
 | 
					
						
							| 
									
										
										
										
											2021-05-25 01:45:08 +08:00
										 |  |  |         $this->userAvatar->destroyAllForUser($user); | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 03:30:08 +08:00
										 |  |  |         // Delete related activities
 | 
					
						
							|  |  |  |         setting()->deleteUserSettings($user->id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  |         if (!empty($newOwnerId)) { | 
					
						
							|  |  |  |             $newOwner = User::query()->find($newOwnerId); | 
					
						
							|  |  |  |             if (!is_null($newOwner)) { | 
					
						
							|  |  |  |                 $this->migrateOwnership($user, $newOwner); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-03 23:12:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Activity::add(ActivityType::USER_DELETE, $user); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @throws NotifyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function ensureDeletable(User $user): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($this->isOnlyAdmin($user)) { | 
					
						
							|  |  |  |             throw new NotifyException(trans('errors.users_cannot_delete_only_admin'), $user->getEditUrl()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($user->system_name === 'public') { | 
					
						
							|  |  |  |             throw new NotifyException(trans('errors.users_cannot_delete_guest'), $user->getEditUrl()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Migrate ownership of items in the system from one user to another. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function migrateOwnership(User $fromUser, User $toUser) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |         $entities = (new EntityProvider())->all(); | 
					
						
							| 
									
										
										
										
											2021-01-02 02:31:01 +08:00
										 |  |  |         foreach ($entities as $instance) { | 
					
						
							|  |  |  |             $instance->newQuery()->where('owned_by', '=', $fromUser->id) | 
					
						
							|  |  |  |                 ->update(['owned_by' => $toUser->id]); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-12-16 03:27:36 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |      * Get an avatar image for a user and set it as their avatar. | 
					
						
							|  |  |  |      * Returns early if avatars disabled or not set in config. | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |     protected function downloadAndAssignUserAvatar(User $user): void | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |         try { | 
					
						
							|  |  |  |             $this->userAvatar->fetchAndAssignToUser($user); | 
					
						
							|  |  |  |         } catch (Exception $e) { | 
					
						
							|  |  |  |             Log::error('Failed to save user avatar image'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |      * Checks if the give user is the only admin. | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |     protected function isOnlyAdmin(User $user): bool | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |         if (!$user->hasSystemRole('admin')) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $adminRole = Role::getSystemRole('admin'); | 
					
						
							|  |  |  |         if ($adminRole->users()->count() > 1) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2016-02-17 05:25:11 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-18 06:11:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |      * Set the assigned user roles via an array of role IDs. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws UserUpdateException | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |     protected function setUserRoles(User $user, array $roles) | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-12-17 01:44:13 +08:00
										 |  |  |         $roles = array_filter(array_values($roles)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |         if ($this->demotingLastAdmin($user, $roles)) { | 
					
						
							|  |  |  |             throw new UserUpdateException(trans('errors.role_cannot_remove_only_admin'), $user->getEditUrl()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $user->roles()->sync($roles); | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 02:09:26 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |      * Check if the given user is the last admin and their new roles no longer | 
					
						
							|  |  |  |      * contains the admin role. | 
					
						
							| 
									
										
										
										
											2018-01-29 02:09:26 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |     protected function demotingLastAdmin(User $user, array $newRoles): bool | 
					
						
							| 
									
										
										
										
											2018-01-29 02:09:26 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  |         if ($this->isOnlyAdmin($user)) { | 
					
						
							|  |  |  |             $adminRole = Role::getSystemRole('admin'); | 
					
						
							|  |  |  |             if (!in_array(strval($adminRole->id), $newRoles)) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-01-29 02:09:26 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-13 20:56:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2018-01-29 02:09:26 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-21 09:19:25 +08:00
										 |  |  | } |