/** * Don't allow updates to credential - must use the ForgotCredentialToken instead * * @param type $id * @param type $data * @return type * @throws InvalidArgumentException */ public function update($id, $data) { if (isset($data['credential'])) { throw new Exception\InvalidArgumentException('Credential cannot be updated. Use ForgotCredentialToken instead.'); } return parent::update($id, $data); }
/** * This will start the credential reset process for an identity. * If the identity is found in the db, a new token is created, and * that token is sent to the identity's email. * * @param type $data * @return type * @throws Exception\LoginFailedException */ public function create($data) { $documentManager = $this->options->getDocumentManager(); $identityMetadata = $documentManager->getClassMetadata($this->options->getIdentityClass()); $criteria = []; if (isset($data['identityName']) && !$data['identityName'] == '') { $criteria['identityName'] = $data['identityName']; } if (isset($data['email']) && $data['email'] != '') { $criteria['email'] = BlockCipherService::encryptValue($data['email'], $identityMetadata->crypt['blockCipher']['email']); } if (count($criteria) == 0) { throw new Exception\InvalidArgumentException('Either identityName or email must be provided'); } $identityRepository = $documentManager->getRepository($this->options->getIdentityClass()); $identity = $identityRepository->findOneBy($criteria); if (!isset($identity)) { throw new Exception\DocumentNotFoundException(); } // create unique recovery code $code = base64_encode(Hash::hash(time(), $identity->getIdentityName())); $code = substr($code, 0, strlen($code) - 2); $expiry = $this->options->getExpiry(); // delete any existing tokens for the identity $documentManager->createQueryBuilder($this->options->getDocumentClass())->remove()->field('identityName')->equals($identity->getIdentityName())->getQuery()->execute(); parent::create(['code' => $code, 'identityName' => $identity->getIdentityName(), 'expires' => $expiry + time()]); //remove the Location header so the token isn't exposed in the response $headers = $this->response->getHeaders(); $headers->removeHeader($headers->get('Location')); $link = '/rest/' . $this->options->getEndpoint() . '/' . $code; // Create email body $body = new ViewModel(['identityName' => $identity->getIdentityName(), 'link' => $link, 'hours' => $expiry / (60 * 60)]); $body->setTemplate('email/forgot-credential'); // Send the email $mail = new Message(); $mail->setBody($this->options->getEmailRenderer()->render($body))->setFrom($this->options->getMailFrom())->addTo(BlockCipherService::decryptValue($identity->getEmail(), $identityMetadata->crypt['blockCipher']['email']))->setSubject($this->options->getMailSubject()); $this->options->getMailTransport()->send($mail); $this->response->setStatusCode(201); return $this->response; }