1 <?php
namespace Tilmeld\Entities;
60 const ETYPE =
'tilmeld_user';
61 const DEFAULT_CLIENT_ENABLED_METHODS = [
68 const DEFAULT_PRIVATE_DATA = [
78 'addressInternational',
94 const DEFAULT_WHITELIST_DATA = [];
96 protected $clientEnabledMethods = User::DEFAULT_CLIENT_ENABLED_METHODS;
97 public static $clientEnabledStaticMethods = [
104 protected $privateData = User::DEFAULT_PRIVATE_DATA;
105 public static $searchRestrictedData = User::DEFAULT_PRIVATE_DATA;
106 protected $whitelistData = User::DEFAULT_WHITELIST_DATA;
107 protected $whitelistTags = [];
118 private $gatekeeperCache = [];
126 private $skipAcWhenSaving =
false;
134 private $descendantGroups =
null;
143 if ((is_int($id) && $id > 0) || is_string($id)) {
145 $entity = Nymph::getEntity(
146 [
'class' => get_class($this)],
150 $entity = Nymph::getEntity(
151 [
'class' => get_class($this)],
155 str_replace([
'\\',
'%',
'_'], [
'\\\\\\\\',
'\%',
'\_'], $id)
160 if (isset($entity)) {
161 $this->guid = $entity->guid;
162 $this->tags = $entity->tags;
163 $this->cdate = $entity->cdate;
164 $this->mdate = $entity->mdate;
165 $this->putData($entity->getData(), $entity->getSData());
166 if (!isset($this->secret)
168 !isset($this->emailChangeDate)
169 || $this->emailChangeDate <
170 strtotime(
'-'.Tilmeld::$config[
'email_rate_limit'])
173 $this->originalEmail = $this->email;
179 $this->enabled =
true;
180 $this->abilities = [];
182 $this->inheritAbilities =
true;
183 $this->addressType =
'us';
194 if (Tilmeld::$config[
'email_usernames'] && $name ==
'username') {
195 if (parent::__get(
'email')) {
196 return parent::__get(
'email');
198 return parent::__get(
'username');
200 return parent::__get($name);
210 if (Tilmeld::$config[
'email_usernames'] && $name ==
'username') {
211 return (parent::__isset(
'email') || parent::__isset(
'username'));
213 return parent::__isset($name);
223 public function __set($name, $value) {
224 if (Tilmeld::$config[
'email_usernames']
225 && ($name ==
'username' 228 parent::__set(
'username', $value);
229 return parent::__set(
'email', $value);
231 return parent::__set($name, $value);
240 if (Tilmeld::$config[
'email_usernames']
241 && ($name ==
'username' 244 parent::__unset(
'username');
245 return parent::__unset(
'email');
247 return parent::__unset($name);
250 public static function current($returnObjectIfNotExist =
false) {
251 if (!isset(Tilmeld::$currentUser)) {
252 return $returnObjectIfNotExist ? self::factory() : null;
254 return Tilmeld::$currentUser;
264 if (!Tilmeld::$config[
'pw_recovery']) {
267 'message' =>
'Account recovery is not allowed.' 271 if (!Tilmeld::$config[
'email_usernames']
272 && $data[
'recoveryType'] ===
'username' 276 $user = Nymph::getEntity(
277 [
'class' =>
'\Tilmeld\Entities\User',
'skip_ac' =>
true],
283 [
'\\\\\\\\',
'\%',
'\_'],
293 'message' =>
'Requested account is not accessible.' 299 'to_phone' => htmlspecialchars(
300 \uMailPHP\Mail::formatPhone($user->phone)
302 'to_timezone' => htmlspecialchars($user->timezone),
304 $user->addressType ==
'us' 307 "{$user->addressStreet} {$user->addressStreet2}" 310 "{$user->addressCity}, {$user->addressState} ".
311 "{$user->addressZip}" 313 :
'<pre>'.htmlspecialchars($user->addressInternational).
'</pre>' 315 $mail = new \uMailPHP\Mail(
316 '\Tilmeld\Entities\Mail\RecoverUsername',
320 } elseif ($data[
'recoveryType'] ===
'password') {
323 $user = User::factory($data[
'account']);
325 if (!isset($user->guid)) {
328 'message' =>
'Requested account is not accessible.' 333 $user->recoverSecret = self::generateSecret($user);
334 $user->recoverSecretTime = time();
335 if (!$user->saveSkipAC()) {
336 return [
'result' =>
false,
'message' =>
'Couldn\'t save user secret.'];
341 'recover_code' => $user->recoverSecret,
342 'time_limit' => htmlspecialchars(
343 Tilmeld::$config[
'pw_recovery_time_limit']
345 'to_phone' => htmlspecialchars(
346 \uMailPHP\Mail::formatPhone($user->phone)
348 'to_timezone' => htmlspecialchars($user->timezone),
350 $user->addressType ==
'us' 353 "{$user->addressStreet} {$user->addressStreet2}" 356 "{$user->addressCity}, {$user->addressState} ".
357 "{$user->addressZip}" 359 :
'<pre>'.htmlspecialchars($user->addressInternational).
'</pre>' 361 $mail = new \uMailPHP\Mail(
362 '\Tilmeld\Entities\Mail\RecoverPassword',
367 return [
'result' =>
false,
'message' =>
'Invalid recovery type.'];
374 'message' =>
'We\'ve sent an email to your registered address. Please '.
375 'check your email to continue with account recovery.' 378 return [
'result' =>
false,
'message' =>
'Couldn\'t send recovery email.'];
389 if (!Tilmeld::$config[
'pw_recovery']) {
392 'message' =>
'Account recovery is not allowed.' 396 $user = User::factory($data[
'username']);
398 if (!isset($user->guid)
399 || !isset($user->recoverSecret)
400 || $data[
'secret'] !== $user->recoverSecret
402 '+'.Tilmeld::$config[
'pw_recovery_time_limit'],
403 $user->recoverSecretTime
408 'message' =>
'The secret code does not match.' 412 if (empty($data[
'password'])) {
413 return [
'result' =>
false,
'message' =>
'Password cannot be empty.'];
416 $user->password($data[
'password']);
417 unset($user->recoverSecret);
418 unset($user->recoverSecretTime);
419 if ($user->saveSkipAC()) {
422 'message' =>
'Your password has been reset. You can now log in using '.
426 return [
'result' =>
false,
'message' =>
'Error saving new password.'];
430 public static function getClientConfig() {
431 $timezones = \DateTimeZone::listIdentifiers();
434 'reg_fields' => Tilmeld::$config[
'reg_fields'],
435 'email_usernames' => Tilmeld::$config[
'email_usernames'],
436 'allow_registration' => Tilmeld::$config[
'allow_registration'],
437 'pw_recovery' => Tilmeld::$config[
'pw_recovery'],
438 'verify_email' => Tilmeld::$config[
'verify_email'],
439 'unverified_access' => Tilmeld::$config[
'unverified_access'],
440 'timezones' => $timezones,
444 public static function generateSecret($user) {
446 hash(
'sha256', uniqid($user->username,
true)),
452 public static function loginUser($data) {
453 if (!isset($data[
'username'])) {
454 return [
'result' =>
false,
'message' =>
'Incorrect login/password.'];
456 $user = User::factory($data[
'username']);
457 $result = $user->login($data);
458 if ($result[
'result']) {
459 $user->updateDataProtection();
460 $result[
'user'] = $user;
465 public function login($data) {
466 if (!isset($this->guid)) {
467 return [
'result' =>
false,
'message' =>
'Incorrect login/password.'];
469 if (!$this->enabled) {
470 return [
'result' =>
false,
'message' =>
'This user is disabled.'];
473 return [
'result' =>
true,
'message' =>
'You are already logged in.'];
476 return [
'result' =>
false,
'message' =>
'Incorrect login/password.'];
481 return [
'result' =>
false,
'message' =>
'Incorrect login/password.'];
485 return [
'result' =>
true,
'message' =>
'You are logged in.'];
495 return [
'result' =>
true,
'message' =>
'You have been logged out.'];
498 public function getAvatar() {
499 if (isset($this->avatar)) {
500 return $this->avatar;
502 $proto = isset($_SERVER[
'HTTPS']) ?
'https' :
'http';
503 if (!isset($this->email) || empty($this->email)) {
504 return $proto.
'://secure.gravatar.com/avatar/?d=mm&s=40';
506 return $proto.
'://secure.gravatar.com/avatar/'.
507 md5(strtolower(trim($this->email))).
'?d=identicon&s=40';
514 if (!isset($this->descendantGroups)) {
515 $this->descendantGroups = [];
516 if (isset($this->group)) {
517 $this->descendantGroups =
518 (array) $this->group->getDescendants();
520 foreach ($this->groups as $curGroup) {
521 $this->descendantGroups =
523 (array) $this->descendantGroups,
524 (array) $curGroup->getDescendants()
528 return $this->descendantGroups;
545 $timezone = date_default_timezone_get();
546 if (!empty($this->timezone)) {
547 $timezone = $this->timezone;
548 } elseif (isset($this->group->guid) && !empty($this->group->timezone)) {
549 $timezone = $this->group->timezone;
550 }
else if (count($this->groups)) {
551 foreach ((array) $this->groups as $curGroup) {
552 if (!empty($curGroup->timezone)) {
553 $timezone = $curGroup->timezone;
558 return $returnDateTimeZoneObject
559 ?
new DateTimeZone($timezone)
563 public function putData($data, $sdata = []) {
564 $return = parent::putData($data, $sdata);
578 $user = self::current();
581 $this->clientEnabledMethods = self::DEFAULT_CLIENT_ENABLED_METHODS;
582 $this->privateData = self::DEFAULT_PRIVATE_DATA;
583 $this->whitelistData = self::DEFAULT_WHITELIST_DATA;
585 if (Tilmeld::$config[
'email_usernames']) {
586 $this->privateData[] =
'username';
589 $isCurrentUser = $user !==
null && $this->is($user);
590 $isNewUser = !isset($this->guid);
592 if ($isCurrentUser) {
594 $this->clientEnabledMethods[] =
'gatekeeper';
595 $this->clientEnabledMethods[] =
'changePassword';
596 $this->clientEnabledMethods[] =
'logout';
597 $this->clientEnabledMethods[] =
'sendEmailVerification';
600 if ($user !==
null && $user->gatekeeper(
'tilmeld/admin')) {
602 $this->privateData = [
606 $this->whitelistData =
false;
607 } elseif ($isCurrentUser || $isNewUser) {
609 $this->whitelistData[] =
'username';
610 $this->whitelistData[] =
'avatar';
611 if (in_array(
'name', Tilmeld::$config[
'user_fields'])) {
612 $this->whitelistData[] =
'nameFirst';
613 $this->whitelistData[] =
'nameMiddle';
614 $this->whitelistData[] =
'nameLast';
615 $this->whitelistData[] =
'name';
617 if (in_array(
'email', Tilmeld::$config[
'user_fields'])) {
618 $this->whitelistData[] =
'email';
620 if (in_array(
'phone', Tilmeld::$config[
'user_fields'])) {
621 $this->whitelistData[] =
'phone';
623 if (in_array(
'timezone', Tilmeld::$config[
'user_fields'])) {
624 $this->whitelistData[] =
'timezone';
626 if (in_array(
'address', Tilmeld::$config[
'user_fields'])) {
627 $this->whitelistData[] =
'addressType';
628 $this->whitelistData[] =
'addressStreet';
629 $this->whitelistData[] =
'addressStreet2';
630 $this->whitelistData[] =
'addressCity';
631 $this->whitelistData[] =
'addressState';
632 $this->whitelistData[] =
'addressZip';
633 $this->whitelistData[] =
'addressInternational';
635 $this->privateData = [
638 'cancelEmailAddress',
664 if (!isset($ability)) {
665 return self::current(
true)->is($this);
668 if ($this->gatekeeperCache) {
669 $abilities =& $this->gatekeeperCache;
671 $abilities = $this->abilities;
672 if ($this->inheritAbilities) {
673 foreach ($this->groups as &$curGroup) {
674 if (!isset($curGroup->guid)) {
677 $abilities = array_merge($abilities, $curGroup->abilities);
680 if (isset($this->group) && isset($this->group->guid)) {
681 $abilities = array_merge($abilities, $this->group->abilities);
684 $this->gatekeeperCache = $abilities;
686 if (!is_array($abilities)) {
690 in_array($ability, $abilities) || in_array(
'system/admin', $abilities)
694 public function clearCache() {
695 $return = parent::clearCache();
696 $this->gatekeeperCache = [];
706 if (!isset($this->guid)) {
710 if (isset($this->secret) && !isset($this->cancelEmailSecret)) {
712 $link = htmlspecialchars(Tilmeld::$config[
'setup_url'].(strpos(Tilmeld::$config[
'setup_url'],
'?') ?
'&' :
'?').
'action=verifyemail&id='.$this->guid.
'&secret='.$this->secret);
714 'verify_link' => $link,
715 'to_phone' => htmlspecialchars(
716 \uMailPHP\Mail::formatPhone($this->phone)
718 'to_timezone' => htmlspecialchars($this->timezone),
720 $this->addressType ==
'us' 723 "{$this->addressStreet} {$this->addressStreet2}" 726 "{$this->addressCity}, {$this->addressState} ".
727 "{$this->addressZip}" 729 :
'<pre>'.htmlspecialchars($this->addressInternational).
'</pre>' 731 $mail = new \uMailPHP\Mail(
732 '\Tilmeld\Entities\Mail\VerifyEmail',
736 $success = $success && $mail->send();
738 if (isset($this->secret) && isset($this->cancelEmailSecret)) {
740 $link = htmlspecialchars(Tilmeld::$config[
'setup_url'].(strpos(Tilmeld::$config[
'setup_url'],
'?') ?
'&' :
'?').
'action=verifyemailchange&id='.$this->guid.
'&secret='.$this->secret);
742 'verify_link' => $link,
743 'old_email' => htmlspecialchars($this->cancelEmailAddress),
744 'new_email' => htmlspecialchars($this->email),
745 'to_phone' => htmlspecialchars(
746 \uMailPHP\Mail::formatPhone($this->phone)
748 'to_timezone' => htmlspecialchars($this->timezone),
750 $this->addressType ==
'us' 753 "{$this->addressStreet} {$this->addressStreet2}" 756 "{$this->addressCity}, {$this->addressState} ".
757 "{$this->addressZip}" 759 :
'<pre>'.htmlspecialchars($this->addressInternational).
'</pre>' 761 $mail = new \uMailPHP\Mail(
762 '\Tilmeld\Entities\Mail\VerifyEmailChange',
766 $success = $success && $mail->send();
768 if (isset($this->cancelEmailSecret)) {
770 $link = htmlspecialchars(Tilmeld::$config[
'setup_url'].(strpos(Tilmeld::$config[
'setup_url'],
'?') ?
'&' :
'?').
'action=cancelemailchange&id='.$this->guid.
'&secret='.$this->cancelEmailSecret);
772 'cancel_link' => $link,
773 'old_email' => htmlspecialchars($this->cancelEmailAddress),
774 'new_email' => htmlspecialchars($this->email),
775 'to_phone' => htmlspecialchars(
776 \uMailPHP\Mail::formatPhone($this->phone)
778 'to_timezone' => htmlspecialchars($this->timezone),
780 $this->addressType ==
'us' 783 "{$this->addressStreet} {$this->addressStreet2}" 786 "{$this->addressCity}, {$this->addressState} ".
787 "{$this->addressZip}" 789 :
'<pre>'.htmlspecialchars($this->addressInternational).
'</pre>' 791 $mail = new \uMailPHP\Mail(
792 '\Tilmeld\Entities\Mail\CancelEmailChange',
796 $success = $success && $mail->send();
809 if (!$group->inArray((array) $this->groups)) {
810 $this->groups[] = $group;
811 return $this->groups;
823 switch (Tilmeld::$config[
'pw_method']) {
825 return ($this->
password == $password);
827 return ($this->
password == hash(
'sha256', $password));
830 return ($this->
password == hash(
'sha256', $password.$this->salt));
842 if ($group->inArray((array) $this->groups)) {
843 foreach ((array) $this->groups as $key => $curGroup) {
844 if ($group->is($curGroup)) {
845 unset($this->groups[$key]);
848 return $this->groups;
860 if (is_numeric($group)) {
861 $group = Group::factory((
int) $group);
863 if (!isset($group->guid)) {
866 return ($group->inArray((array) $this->groups) || $group->is($this->group));
876 if (is_numeric($group)) {
877 $group = Group::factory((
int) $group);
879 if (!isset($group->guid)) {
883 if (isset($this->group->guid) && $this->group->isDescendant($group)) {
886 foreach ((array) $this->groups as $curGroup) {
887 if ($curGroup->isDescendant($group)) {
901 if (!isset($data[
'password']) || (
string) $data[
'password'] ===
'') {
902 return [
'result' =>
false,
'message' =>
'Please specify a password.'];
905 return [
'result' =>
false,
'message' =>
'Incorrect password.'];
907 $this->passwordTemp = (string) $data[
'password'];
909 return [
'result' =>
true,
'message' =>
'Your password has been changed.'];
911 return [
'result' =>
false,
'message' =>
'Couldn\'t save new password.'];
922 switch (Tilmeld::$config[
'pw_method']) {
928 return $this->
password = hash(
'sha256', $password);
931 $this->salt = hash(
'sha256', rand());
932 return $this->
password = hash(
'sha256', $password.$this->salt);
943 if (!Tilmeld::$config[
'email_usernames']) {
944 if (empty($this->username)) {
945 return [
'result' =>
false,
'message' =>
'Please specify a username.'];
947 if (Tilmeld::$config[
'max_username_length'] > 0
948 && strlen($this->username) > Tilmeld::$config[
'max_username_length']
952 'message' =>
'Usernames must not exceed '.
953 Tilmeld::$config[
'max_username_length'].
' characters.' 957 str_split($this->username),
958 str_split(Tilmeld::$config[
'valid_chars'])
962 'message' => Tilmeld::$config[
'valid_chars_notice']
965 if (!preg_match(Tilmeld::$config[
'valid_regex'], $this->username)) {
968 'message' => Tilmeld::$config[
'valid_regex_notice']
976 [
'\\\\\\\\',
'\%',
'\_'],
981 if (isset($this->guid)) {
982 $selector[
'!guid'] = $this->guid;
984 $test = Nymph::getEntity(
985 [
'class' =>
'\Tilmeld\Entities\User',
'skip_ac' =>
true],
988 if (isset($test->guid)) {
989 return [
'result' =>
false,
'message' =>
'That username is taken.'];
995 isset($this->guid) ?
'Username is valid.' :
'Username is available!' 999 if (empty($this->username)) {
1000 return [
'result' =>
false,
'message' =>
'Please specify an email.'];
1002 if (Tilmeld::$config[
'max_username_length'] > 0
1003 && strlen($this->username) > Tilmeld::$config[
'max_username_length']
1007 'message' =>
'Emails must not exceed '.
1008 Tilmeld::$config[
'max_username_length'].
' characters.' 1023 if (empty($this->email)) {
1024 if (Tilmeld::$config[
'verify_email']) {
1025 return [
'result' =>
false,
'message' =>
'Please specify an email.'];
1027 return [
'result' =>
true,
'message' =>
''];
1031 '/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i',
1036 'message' =>
'Email must be a correctly formatted address.' 1042 str_replace([
'\\',
'%',
'_'], [
'\\\\\\\\',
'\%',
'\_'], $this->email)
1045 if (isset($this->guid)) {
1046 $selector[
'!guid'] = $this->guid;
1048 $test = Nymph::getEntity(
1049 [
'class' =>
'\Tilmeld\Entities\User',
'skip_ac' =>
true],
1052 if (isset($test->guid)) {
1055 'message' =>
'That email address is already registered.' 1062 isset($this->guid) ?
'Email is valid.' :
'Email address is valid!' 1074 if (empty($this->phone)) {
1075 return [
'result' =>
false,
'message' =>
'Please specify a phone number.'];
1078 $stripToDigits = preg_replace(
'/\D/',
'', $this->phone);
1079 if (!preg_match(
'/\d{10}/', $stripToDigits)) {
1083 'Phone must contain 10 digits, but formatting does not matter.' 1087 'strict' => [
'phone', $stripToDigits]
1089 if (isset($this->guid)) {
1090 $selector[
'!guid'] = $this->guid;
1092 $test = Nymph::getEntity(
1093 [
'class' =>
'\Tilmeld\Entities\User',
'skip_ac' =>
true],
1096 if (isset($test->guid)) {
1097 return [
'result' =>
false,
'message' =>
'Phone number is in use.'];
1103 isset($this->guid) ?
'Phone number is valid.' :
'Phone number is valid!' 1108 public function register($data) {
1109 if (!Tilmeld::$config[
'allow_registration']) {
1112 'loggedin' =>
false,
1113 'message' =>
'Registration is not allowed.' 1116 if (isset($this->guid)) {
1119 'loggedin' =>
false,
1120 'message' =>
'This is already a registered user.' 1123 if (!isset($data[
'password']) || (string) $data[
'password'] ===
'') {
1126 'loggedin' =>
false,
1127 'message' =>
'Password is a required field.' 1131 if (!$unCheck[
'result']) {
1135 $this->
password((
string) $data[
'password']);
1136 if (in_array(
'name', Tilmeld::$config[
'reg_fields'])) {
1139 (!empty($this->nameMiddle) ?
' '.$this->nameMiddle :
'').
1140 (!empty($this->nameLast) ?
' '.$this->nameLast :
'');
1141 if ($this->name ===
'') {
1142 $this->name = $this->username;
1145 if (Tilmeld::$config[
'email_usernames']) {
1146 $this->email = $this->username;
1150 $primaryGroup =
null;
1151 $generatedPrimaryGroup =
false;
1152 if (Tilmeld::$config[
'generate_primary']) {
1154 $primaryGroup = Group::factory();
1155 $primaryGroup->groupname = $this->username;
1156 $primaryGroup->avatar = $this->avatar;
1157 $primaryGroup->name = $this->name;
1158 $primaryGroup->email = $this->email;
1159 $primaryGroup->parent = Nymph::getEntity(
1160 [
'class' =>
'\Tilmeld\Entities\Group'],
1162 'equal' => [
'defaultPrimary',
true]
1165 if (!isset($primaryGroup->parent) || !isset($primaryGroup->group->guid)) {
1166 unset($primaryGroup->parent);
1168 if (!$primaryGroup->saveSkipAC()) {
1171 'loggedin' =>
false,
1172 'message' =>
'Error creating primary group for user.' 1175 $this->group = $primaryGroup;
1176 $generatedPrimaryGroup = $primaryGroup;
1179 $this->group = Nymph::getEntity(
1180 [
'class' =>
'\Tilmeld\Entities\Group'],
1182 'equal' => [
'defaultPrimary',
true]
1185 if (!isset($this->group) || !isset($this->group->guid)) {
1186 unset($this->group);
1192 if (Tilmeld::$config[
'verify_email']
1193 && Tilmeld::$config[
'unverified_access']
1196 $this->groups = (array) Nymph::getEntities(
1197 [
'class' =>
'\Tilmeld\Entities\Group'],
1199 'equal' => [
'unverifiedSecondary',
true]
1204 $this->groups = (array) Nymph::getEntities(
1205 [
'class' =>
'\Tilmeld\Entities\Group'],
1207 'equal' => [
'defaultSecondary',
true]
1212 if (Tilmeld::$config[
'verify_email']) {
1214 if (!Tilmeld::$config[
'unverified_access']) {
1215 $this->enabled =
false;
1218 $this->enabled =
true;
1223 if (Tilmeld::$config[
'create_admin']) {
1224 $otherUsers = Nymph::getEntities(
1225 [
'class' =>
'\Tilmeld\Entities\User',
'skip_ac' =>
true,
'limit' => 1]
1228 if ($otherUsers === []) {
1229 $this->
grant(
'system/admin');
1230 $this->enabled =
true;
1237 'user_username' => htmlspecialchars($this->username),
1238 'user_name' => htmlspecialchars($this->name),
1239 'user_first_name' => htmlspecialchars($this->nameFirst),
1240 'user_last_name' => htmlspecialchars($this->nameLast),
1241 'user_email' => htmlspecialchars($this->email),
1242 'user_phone' => htmlspecialchars(
1243 \uMailPHP\Mail::formatPhone($this->phone)
1245 'user_timezone' => htmlspecialchars($this->timezone),
1247 $this->addressType ==
'us' 1250 "{$this->addressStreet} {$this->addressStreet2}" 1253 "{$this->addressCity}, {$this->addressState} ".
1254 "{$this->addressZip}" 1256 :
'<pre>'.htmlspecialchars($this->addressInternational).
'</pre>' 1258 $mail = new \uMailPHP\Mail(
1259 '\Tilmeld\Entities\Mail\UserRegistered',
1268 if ($primaryGroup) {
1269 $primaryGroup->user = $this;
1270 if (!$primaryGroup->saveSkipAC()) {
1271 $message .=
"Your account was created, but your primary group ".
1272 "couldn't be assigned to you. You should ask an administrator to ".
1278 if (Tilmeld::$config[
'verify_email']
1279 && !Tilmeld::$config[
'unverified_access']
1281 $message .=
"Almost there. An email has been sent to {$this->email} ".
1282 "with a verification link for you to finish registration.";
1284 } elseif (Tilmeld::$config[
'verify_email']
1285 && Tilmeld::$config[
'unverified_access']
1289 $message .=
"You're now logged in! An email has been sent to ".
1290 "{$this->email} with a verification link for you to finish ".
1296 $message .=
'You\'re now registered and logged in!';
1299 return [
'result' =>
true,
'loggedin' => $loggedin,
'message' => $message];
1301 if ($generatedPrimaryGroup) {
1302 $generatedPrimaryGroup->delete();
1306 'loggedin' =>
false,
1307 'message' =>
'Error registering user.' 1310 }
catch (\Exception $e) {
1311 if ($generatedPrimaryGroup) {
1312 $generatedPrimaryGroup->delete();
1318 public function save() {
1319 if (!isset($this->username)) {
1323 $sendVerification =
false;
1326 $this->username = trim($this->username);
1328 if (!Tilmeld::$config[
'email_usernames']) {
1329 $this->email = trim($this->email);
1331 $this->nameFirst = trim($this->nameFirst);
1332 $this->nameMiddle = trim($this->nameMiddle);
1333 $this->nameLast = trim($this->nameLast);
1334 $this->phone = trim($this->phone);
1337 (!empty($this->nameMiddle) ?
' '.$this->nameMiddle :
'').
1338 (!empty($this->nameLast) ?
' '.$this->nameLast :
'');
1342 if (!$unCheck[
'result']) {
1343 throw new \Tilmeld\Exceptions\BadUsernameException($unCheck[
'message']);
1345 if (!Tilmeld::$config[
'email_usernames']) {
1347 if (!$emCheck[
'result']) {
1348 throw new \Tilmeld\Exceptions\BadEmailException($emCheck[
'message']);
1356 if (Tilmeld::$config[
'verify_email']) {
1358 if (!isset($this->guid)) {
1359 $this->secret = self::generateSecret($this);
1360 $sendVerification =
true;
1361 } elseif (!empty($this->originalEmail)
1362 && $this->originalEmail !== $this->email
1365 if (Tilmeld::$config[
'email_rate_limit'] !==
'' 1366 && isset($this->emailChangeDate)
1367 && $this->emailChangeDate >
1368 strtotime(
'-'.Tilmeld::$config[
'email_rate_limit'])
1370 throw new \Tilmeld\Exceptions\EmailChangeRateLimitExceededException(
1371 'You already changed your email address recently. Please wait '.
1373 \uMailPHP\Mail::formatDate(
1375 '+'.Tilmeld::$config[
'email_rate_limit'],
1376 $this->emailChangeDate
1380 ' to change your email address again.' 1383 if (!isset($this->secret)
1387 !isset($this->emailChangeDate) ||
1388 $this->emailChangeDate <
1389 strtotime(
'-'.Tilmeld::$config[
'email_rate_limit'])
1394 $this->cancelEmailAddress = $this->originalEmail;
1395 $this->cancelEmailSecret = self::generateSecret($this);
1396 $this->emailChangeDate = time();
1398 $this->secret = self::generateSecret($this);
1399 $sendVerification =
true;
1402 } elseif (isset($this->guid)
1403 && !empty($this->originalEmail)
1404 && $this->originalEmail !== $this->email
1408 !isset($this->emailChangeDate) ||
1409 $this->emailChangeDate <
1410 strtotime(
'-'.Tilmeld::$config[
'email_rate_limit'])
1416 $this->cancelEmailAddress = $this->originalEmail;
1417 $this->cancelEmailSecret = self::generateSecret($this);
1418 $sendVerification =
true;
1422 if (!isset($this->
password) && !isset($this->passwordTemp)) {
1423 throw new \Tilmeld\Exceptions\BadDataException(
'A password is required.');
1426 if (isset($this->passwordTemp) && $this->passwordTemp !==
'') {
1427 $this->
password($this->passwordTemp);
1429 unset($this->passwordTemp);
1432 Tilmeld::$config[
'validator_user']->assert($this->getValidatable());
1434 }
catch (\Respect\Validation\Exceptions\NestedValidationException $exception) {
1435 throw new \Tilmeld\Exceptions\BadDataException(
1436 $exception->getFullMessage()
1440 if (isset($this->group->user) && $this->is($this->group->user)) {
1442 $this->group->groupname = $this->username;
1443 $this->group->avatar = $this->avatar;
1444 $this->group->email = $this->email;
1445 $this->group->name = $this->name;
1446 $this->group->saveSkipAC();
1449 $return = parent::save();
1451 if ($sendVerification) {
1456 if (self::current(
true)->is($this)) {
1461 $this->descendantGroups =
null;
1470 $this->skipAcWhenSaving =
true;
1471 return $this->save();
1474 public function tilmeldSaveSkipAC() {
1475 if ($this->skipAcWhenSaving) {
1476 $this->skipAcWhenSaving =
false;
1482 public function delete() {
1486 if (self::current(
true)->is($this)) {
1489 return parent::delete();
getTimezone($returnDateTimeZoneObject=false)
Return the user's timezone.
& __get($name)
Override the magic method, for email usernames.
sendEmailVerification()
Send the user email verification/change/cancellation links.
addGroup($group)
Add the user to a (secondary) group.
gatekeeper($ability=null)
Check to see if a user has an ability.
static fillSession($user)
Fill session user data.
inGroup($group=null)
Check whether the user is in a (primary or secondary) group.
logout()
Log a user out of the system.
static gatekeeper($ability=null)
Check to see if the current user has an ability.
static recover($data)
Recover account details.
__set($name, $value)
Override the magic method, for email usernames.
static sendRecoveryLink($data)
Send an account recovery link.
grant($ability)
Grant an ability.
checkPassword($password)
Check the given password against the user's.
isDescendant($group=null)
Check whether the user is a descendant of a group.
changePassword($data)
A frontend accessible method to change the user's password.
updateDataProtection($user=null)
Update the data protection arrays for a user.
__unset($name)
Override the magic method, for email usernames.
__isset($name)
Override the magic method, for email usernames.
checkPhone()
Check that a phone number is unique.
static login($user, $sendAuthHeader)
Logs the given user into the system.
saveSkipAC()
This should never be accessible on the client.
getDescendantGroups()
Get the user's group descendants.
checkUsername()
Check that a username is valid.
password($password)
Change the user's password.
checkEmail()
Check that an email is unique.
delGroup($group)
Remove the user from a (secondary) group.
static logout()
Logs the current user out of the system.
__construct($id=0)
Load a user.