blob: b735b03b2abbdae0454979f4249a004d686dafd6 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace LdapRecord\Models\ActiveDirectory;
4
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +01005use Carbon\Carbon;
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02006use Illuminate\Contracts\Auth\Authenticatable;
7use LdapRecord\Models\ActiveDirectory\Concerns\HasPrimaryGroup;
8use LdapRecord\Models\ActiveDirectory\Scopes\RejectComputerObjectClass;
9use LdapRecord\Models\Concerns\CanAuthenticate;
10use LdapRecord\Models\Concerns\HasPassword;
11use LdapRecord\Query\Model\Builder;
12
13class User extends Entry implements Authenticatable
14{
15 use HasPassword;
16 use HasPrimaryGroup;
17 use CanAuthenticate;
18
19 /**
20 * The password's attribute name.
21 *
22 * @var string
23 */
24 protected $passwordAttribute = 'unicodepwd';
25
26 /**
27 * The password's hash method.
28 *
29 * @var string
30 */
31 protected $passwordHashMethod = 'encode';
32
33 /**
34 * The object classes of the LDAP model.
35 *
36 * @var array
37 */
38 public static $objectClasses = [
39 'top',
40 'person',
41 'organizationalperson',
42 'user',
43 ];
44
45 /**
46 * The attributes that should be mutated to dates.
47 *
48 * @var array
49 */
50 protected $dates = [
51 'lastlogon' => 'windows-int',
52 'lastlogoff' => 'windows-int',
53 'pwdlastset' => 'windows-int',
54 'lockouttime' => 'windows-int',
55 'accountexpires' => 'windows-int',
56 'badpasswordtime' => 'windows-int',
57 'lastlogontimestamp' => 'windows-int',
58 ];
59
60 /**
61 * @inheritdoc
62 */
63 protected static function boot()
64 {
65 parent::boot();
66
67 // Here we will add a global scope to reject the 'computer' object
68 // class. This is needed due to computer objects containing all
69 // of the ActiveDirectory 'user' object classes. Without
70 // this scope, they would be included in results.
71 static::addGlobalScope(new RejectComputerObjectClass());
72 }
73
74 /**
75 * The groups relationship.
76 *
77 * Retrieves groups that the user is apart of.
78 *
79 * @return \LdapRecord\Models\Relations\HasMany
80 */
81 public function groups()
82 {
83 return $this->hasMany(Group::class, 'member')->with($this->primaryGroup());
84 }
85
86 /**
87 * The manager relationship.
88 *
89 * Retrieves the manager of the user.
90 *
91 * @return \LdapRecord\Models\Relations\HasOne
92 */
93 public function manager()
94 {
95 return $this->hasOne(static::class, 'manager');
96 }
97
98 /**
99 * The primary group relationship of the current user.
100 *
101 * Retrieves the primary group the user is apart of.
102 *
103 * @return \LdapRecord\Models\Relations\HasOne
104 */
105 public function primaryGroup()
106 {
107 return $this->hasOnePrimaryGroup(Group::class, 'primarygroupid');
108 }
109
110 /**
111 * Scopes the query to exchange mailbox users.
112 *
113 * @param Builder $query
114 *
115 * @return Builder
116 */
117 public function scopeWhereHasMailbox(Builder $query)
118 {
119 return $query->whereHas('msExchMailboxGuid');
120 }
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +0100121
122 /**
123 * Scopes the query to users having a lockout value set.
124 *
125 * @param Builder $query
126 *
127 * @return Builder
128 */
129 public function scopeWhereHasLockout(Builder $query)
130 {
131 return $query->where('lockoutTime', '>=', 1);
132 }
133
134 /**
135 * Determine if the user is locked out using the domains LockoutDuration group policy value.
136 *
137 * @see https://ldapwiki.com/wiki/Active%20Directory%20Account%20Lockout
138 * @see https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/account-lockout-duration
139 *
140 * @param string|int $localTimezone
141 * @param int|null $durationInMinutes
142 *
143 * @return bool
144 */
145 public function isLockedOut($localTimezone, $durationInMinutes = null)
146 {
147 $time = $this->getFirstAttribute('lockouttime');
148
149 if (! $time instanceof Carbon) {
150 return false;
151 }
152
153 is_int($localTimezone)
154 ? $time->addMinutes($localTimezone)
155 : $time->setTimezone($localTimezone)->addMinutes($durationInMinutes ?: 0);
156
157 return ! $time->isPast();
158 }
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +0200159}