use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
+use Friendica\Model\Photo;
+use Friendica\Model\TwoFactor\AppSpecificPassword;
use Friendica\Object\Image;
use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings;
+use Friendica\Worker\Delivery;
use LightOpenID;
/**
}
}
+ /**
+ * Get a user based on its email
+ *
+ * @param string $email
+ * @param array $fields
+ *
+ * @return array|boolean User record if it exists, false otherwise
+ *
+ * @throws Exception
+ */
+ public static function getByEmail($email, array $fields = [])
+ {
+ return DBA::selectFirst('user', $fields, ['email' => $email]);
+ }
+
/**
* @brief Get owner data by user id
*
* @param int $uid
+ * @param boolean $check_valid Test if data is invalid and correct it
* @return boolean|array
* @throws Exception
*/
- public static function getOwnerDataById($uid) {
+ public static function getOwnerDataById($uid, $check_valid = true) {
$r = DBA::fetchFirst("SELECT
`contact`.*,
`user`.`prvkey` AS `uprvkey`,
return false;
}
+ if (!$check_valid) {
+ return $r;
+ }
+
// Check if the returned data is valid, otherwise fix it. See issue #6122
+
+ // Check for correct url and normalised nurl
$url = System::baseUrl() . '/profile/' . $r['nickname'];
- $addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
+ $repair = ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url']));
+
+ if (!$repair) {
+ // Check if "addr" is present and correct
+ $addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
+ $repair = ($addr != $r['addr']);
+ }
+
+ if (!$repair) {
+ // Check if the avatar field is filled and the photo directs to the correct path
+ $avatar = Photo::selectFirst(['resource-id'], ['uid' => $uid, 'profile' => true]);
+ if (DBA::isResult($avatar)) {
+ $repair = empty($r['avatar']) || !strpos($r['photo'], $avatar['resource-id']);
+ }
+ }
- if (($addr != $r['addr']) || ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url']))) {
+ if ($repair) {
Contact::updateSelfFromUserID($uid);
+ // Return the corrected data and avoid a loop
+ $r = self::getOwnerDataById($uid, false);
}
return $r;
/**
* Authenticate a user with a clear text password
*
- * @brief Authenticate a user with a clear text password
- * @param mixed $user_info
+ * @brief Authenticate a user with a clear text password
+ * @param mixed $user_info
* @param string $password
+ * @param bool $third_party
* @return int|boolean
* @deprecated since version 3.6
- * @see User::getIdFromPasswordAuthentication()
+ * @see User::getIdFromPasswordAuthentication()
*/
- public static function authenticate($user_info, $password)
+ public static function authenticate($user_info, $password, $third_party = false)
{
try {
- return self::getIdFromPasswordAuthentication($user_info, $password);
+ return self::getIdFromPasswordAuthentication($user_info, $password, $third_party);
} catch (Exception $ex) {
return false;
}
* Returns the user id associated with a successful password authentication
*
* @brief Authenticate a user with a clear text password
- * @param mixed $user_info
+ * @param mixed $user_info
* @param string $password
+ * @param bool $third_party
* @return int User Id if authentication is successful
* @throws Exception
*/
- public static function getIdFromPasswordAuthentication($user_info, $password)
+ public static function getIdFromPasswordAuthentication($user_info, $password, $third_party = false)
{
$user = self::getAuthenticationInfo($user_info);
- if (strpos($user['password'], '$') === false) {
+ if ($third_party && PConfig::get($user['uid'], '2fa', 'verified')) {
+ // Third-party apps can't verify two-factor authentication, we use app-specific passwords instead
+ if (AppSpecificPassword::authenticateUser($user['uid'], $password)) {
+ return $user['uid'];
+ }
+ } elseif (strpos($user['password'], '$') === false) {
//Legacy hash that has not been replaced by a new hash yet
if (self::hashPasswordLegacy($password) === $user['password']) {
self::updatePasswordHashed($user['uid'], self::hashPassword($password));
// The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php)
DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc('now + 7 day')], ['uid' => $uid]);
- Worker::add(PRIORITY_HIGH, 'Notifier', 'removeme', $uid);
+ Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::REMOVAL, $uid);
// Send an update to the directory
$self = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]);