'required|between:6,255|unique:users', 'avatar' => 'nullable|image|max:4000', 'username' => 'required|between:2,255|unique:users', 'password' => 'required:create|between:8,255|confirmed', 'password_confirmation' => 'required_with:password|between:8,255', ]; /** * @var array Relations */ public $belongsToMany = [ 'groups' => [UserGroup::class, 'table' => 'users_groups'], 'chatrooms' => [ 'TPS\Birzha\Models\Chatroom', 'table'=>'tps_birzha_chatrooms_users', 'delete' => true, 'softDelete' => true ], 'categories' => [ 'TPS\Birzha\Models\Category', 'table'=>'tps_birzha_users_categories', 'delete' => true, 'softDelete' => true ], ]; public $attachOne = [ 'avatar' => \System\Models\File::class ]; public $hasMany = [ 'products' => ['TPS\Birzha\Models\Product', 'key' => 'vendor_id', 'softDelete' => true], 'transactions' => ['TPS\Birzha\Models\Transaction', 'softDelete' => true], 'exchangerequests' => ['TPS\Birzha\Models\Exchangerequest', 'softDelete' => true], 'sliders' => ['TPS\Birzha\Models\UserSliders', 'softDelete' => true], 'favourites' => ['TPS\Birzha\Models\Favourites', 'softDelete' => true, 'table' => 'tps_birzha_favourites'], 'comments' => ['TPS\Birzha\Models\Comment','table' => 'tps_birzha_comments'], 'orders' => ['TPS\Birzha\Models\Orders','table' => 'tps_birzha_orders'], 'vendor_sales' => ['TPS\Birzha\Models\VendorSales', 'key' => 'vendor_id', 'softDelete' => true], ]; /** * @var array The attributes that are mass assignable. */ protected $fillable = [ 'name', 'surname', 'login', 'username', 'email', 'password', 'password_confirmation', 'created_ip_address', 'last_ip_address' ]; /** * Reset guarded fields, because we use $fillable instead. * @var array The attributes that aren't mass assignable. */ protected $guarded = ['*']; /** * Purge attributes from data set. */ protected $purgeable = ['password_confirmation', 'send_invite']; protected $dates = [ 'last_seen', 'deleted_at', 'created_at', 'updated_at', 'activated_at', 'last_login' ]; public static $loginAttribute = null; /** * Sends the confirmation email to a user, after activating. * @param string $code * @return bool */ public function attemptActivation($code) { if ($this->trashed()) { if ($code === $this->activation_code) { $this->restore(); } else { return false; } } else { $result = parent::attemptActivation($code); if ($result === false) { return false; } } Event::fire('rainlab.user.activate', [$this]); return true; } /** * Converts a guest user to a registered one and sends an invitation notification. * @return void */ public function convertToRegistered($sendNotification = true) { // Already a registered user if (!$this->is_guest) { return; } if ($sendNotification) { $this->generatePassword(); } $this->is_guest = false; $this->save(); if ($sendNotification) { $this->sendInvitation(); } } // // Constructors // /** * findByEmail looks up a user by their email address. * @return self */ public static function findByEmail($email) { if (!$email) { return; } return self::where('email', $email)->first(); } // // Getters // /** * clearPersistCode will forcibly sign the user out */ public function clearPersistCode() { $this->persist_code = null; $this->timestamps = false; $this->save(); } /** * Gets a code for when the user is persisted to a cookie or session which identifies the user. * @return string */ public function getPersistCode() { $block = UserSettings::get('block_persistence', false); if ($block || !$this->persist_code) { return parent::getPersistCode(); } return $this->persist_code; } /** * Returns the public image file path to this user's avatar. */ public function getAvatarThumb($size = 25, $options = null) { if (is_string($options)) { $options = ['default' => $options]; } elseif (!is_array($options)) { $options = []; } // Default is "mm" (Mystery man) $default = array_get($options, 'default', 'mm'); if ($this->avatar) { return $this->avatar->getThumb($size, $size, $options); } else { return '//www.gravatar.com/avatar/'. md5(strtolower(trim($this->email))). '?s='.$size. '&d='.urlencode($default); } } /** * Returns the name for the user's login. * @return string */ public function getLoginName() { if (static::$loginAttribute !== null) { return static::$loginAttribute; } return static::$loginAttribute = UserSettings::get('login_attribute', UserSettings::LOGIN_EMAIL); } /** * Returns the minimum length for a new password from settings. * @return int */ public static function getMinPasswordLength() { return Config::get('rainlab.user::minPasswordLength', 8); } // // Scopes // /** * scopeIsActivated */ public function scopeIsActivated($query) { return $query->where('is_activated', 1); } public function scopeIsFeatured($query) { return $query->where('is_featured', 1)->where('type', '!=', 'simple'); } /** * scopeFilterByGroup */ public function scopeFilterByGroup($query, $filter) { return $query->whereHas('groups', function($group) use ($filter) { $group->whereIn('id', $filter); }); } // // Events // /** * beforeValidate event * @return void */ public function beforeValidate() { /* * Guests are special */ if ($this->is_guest && !$this->password) { $this->generatePassword(); } /* * When the username is not used, the email is substituted. */ if ( (!$this->username) || ($this->isDirty('email') && $this->getOriginal('email') == $this->username) ) { $this->username = $this->email; } /* * Apply Password Length Settings */ $minPasswordLength = static::getMinPasswordLength(); $this->rules['password'] = "required:create|between:$minPasswordLength,255|confirmed"; $this->rules['password_confirmation'] = "required_with:password|between:$minPasswordLength,255"; } /** * afterCreate event * @return void */ public function afterCreate() { $this->restorePurgedValues(); if ($this->send_invite) { $this->sendInvitation(); } } /** * beforeLogin event * @return void */ public function beforeLogin() { if ($this->is_guest) { $login = $this->getLogin(); throw new AuthException(sprintf( 'Cannot login user "%s" as they are not registered.', $login )); } parent::beforeLogin(); } /** * afterLogin event * @return void */ public function afterLogin() { $this->last_login = $this->freshTimestamp(); if ($this->trashed()) { $this->restore(); Mail::sendTo($this, 'rainlab.user::mail.reactivate', [ 'name' => $this->name ]); Event::fire('rainlab.user.reactivate', [$this]); } else { parent::afterLogin(); } Event::fire('rainlab.user.login', [$this]); } /** * afterDelete event * @return void */ public function afterDelete() { if ($this->isSoftDelete()) { Event::fire('rainlab.user.deactivate', [$this]); return; } $this->avatar && $this->avatar->delete(); parent::afterDelete(); } // // Banning // /** * Ban this user, preventing them from signing in. * @return void */ public function ban() { Auth::findThrottleByUserId($this->id)->ban(); } /** * Remove the ban on this user. * @return void */ public function unban() { Auth::findThrottleByUserId($this->id)->unban(); } /** * Check if the user is banned. * @return bool */ public function isBanned() { $throttle = Auth::createThrottleModel()->where('user_id', $this->id)->first(); return $throttle ? $throttle->is_banned : false; } // // Suspending // /** * Check if the user is suspended. * @return bool */ public function isSuspended() { return Auth::findThrottleByUserId($this->id)->checkSuspended(); } /** * Remove the suspension on this user. * @return void */ public function unsuspend() { Auth::findThrottleByUserId($this->id)->unsuspend(); } // // IP Recording and Throttle // /** * Records the last_ip_address to reflect the last known IP for this user. * @param string|null $ipAddress * @return void */ public function touchIpAddress($ipAddress) { $this ->newQuery() ->where('id', $this->id) ->update(['last_ip_address' => $ipAddress]) ; } /** * Returns true if IP address is throttled and cannot register * again. Maximum 3 registrations every 60 minutes. * @param string|null $ipAddress * @return bool */ public static function isRegisterThrottled($ipAddress) { if (!$ipAddress) { return false; } $timeLimit = Carbon::now()->subMinutes(60); $count = static::make() ->where('created_ip_address', $ipAddress) ->where('created_at', '>', $timeLimit) ->count() ; return $count > 2; } // // Last Seen // /** * Checks if the user has been seen in the last 5 minutes, and if not, * updates the last_seen timestamp to reflect their online status. * @return void */ public function touchLastSeen() { if ($this->isOnline()) { return; } $oldTimestamps = $this->timestamps; $this->timestamps = false; $this ->newQuery() ->where('id', $this->id) ->update(['last_seen' => $this->freshTimestamp()]) ; $this->last_seen = $this->freshTimestamp(); $this->timestamps = $oldTimestamps; } /** * Returns true if the user has been active within the last 5 minutes. * @return bool */ public function isOnline() { if (!$this->last_seen) { return false; } return $this->last_seen > $this->freshTimestamp()->subMinutes(5); } /** * Returns the date this user was last seen. * @deprecated use last_seen attribute * @return Carbon\Carbon */ public function getLastSeen() { return $this->last_seen ?: $this->created_at; } // // Utils // /** * Returns the variables available when sending a user notification. * @return array */ public function getNotificationVars() { $vars = [ 'name' => $this->name, 'email' => $this->email, 'username' => $this->username, 'login' => $this->getLogin(), 'password' => $this->getOriginalHashValue('password') ]; /* * Extensibility */ $result = Event::fire('rainlab.user.getNotificationVars', [$this]); if ($result && is_array($result)) { $vars = call_user_func_array('array_merge', $result) + $vars; } return $vars; } /** * sendInvitation sends an invitation to the user using template * "rainlab.user::mail.invite" * @return void */ protected function sendInvitation() { Mail::sendTo($this, 'rainlab.user::mail.invite', $this->getNotificationVars()); } /** * generatePassword assigns this user with a random password. * @return void */ protected function generatePassword() { $this->password = $this->password_confirmation = Str::random(static::getMinPasswordLength()); } }