33
33
use SilverStripe \ORM \ManyManyList ;
34
34
use SilverStripe \ORM \Map ;
35
35
use SilverStripe \ORM \SS_List ;
36
+ use SilverStripe \ORM \UnsavedRelationList ;
36
37
use SilverStripe \ORM \ValidationException ;
37
38
use SilverStripe \ORM \ValidationResult ;
38
39
60
61
*/
61
62
class Member extends DataObject
62
63
{
63
-
64
64
private static $ db = array (
65
- 'FirstName ' => 'Varchar ' ,
66
- 'Surname ' => 'Varchar ' ,
67
- 'Email ' => 'Varchar(254) ' , // See RFC 5321, Section 4.5.3.1.3. (256 minus the < and > character)
68
- 'TempIDHash ' => 'Varchar(160) ' , // Temporary id used for cms re-authentication
69
- 'TempIDExpired ' => 'Datetime ' , // Expiry of temp login
70
- 'Password ' => 'Varchar(160) ' ,
71
- 'AutoLoginHash ' => 'Varchar(160) ' , // Used to auto-login the user on password reset
72
- 'AutoLoginExpired ' => 'Datetime ' ,
65
+ 'FirstName ' => 'Varchar ' ,
66
+ 'Surname ' => 'Varchar ' ,
67
+ 'Email ' => 'Varchar(254) ' , // See RFC 5321, Section 4.5.3.1.3. (256 minus the < and > character)
68
+ 'TempIDHash ' => 'Varchar(160) ' , // Temporary id used for cms re-authentication
69
+ 'TempIDExpired ' => 'Datetime ' , // Expiry of temp login
70
+ 'Password ' => 'Varchar(160) ' ,
71
+ 'AutoLoginHash ' => 'Varchar(160) ' , // Used to auto-login the user on password reset
72
+ 'AutoLoginExpired ' => 'Datetime ' ,
73
73
// This is an arbitrary code pointing to a PasswordEncryptor instance,
74
74
// not an actual encryption algorithm.
75
75
// Warning: Never change this field after its the first password hashing without
76
76
// providing a new cleartext password as well.
77
77
'PasswordEncryption ' => "Varchar(50) " ,
78
- 'Salt ' => 'Varchar(50) ' ,
79
- 'PasswordExpiry ' => 'Date ' ,
80
- 'LockedOutUntil ' => 'Datetime ' ,
81
- 'Locale ' => 'Varchar(6) ' ,
78
+ 'Salt ' => 'Varchar(50) ' ,
79
+ 'PasswordExpiry ' => 'Date ' ,
80
+ 'LockedOutUntil ' => 'Datetime ' ,
81
+ 'Locale ' => 'Varchar(6) ' ,
82
82
// handled in registerFailedLogin(), only used if $lock_out_after_incorrect_logins is set
83
- 'FailedLoginCount ' => 'Int ' ,
83
+ 'FailedLoginCount ' => 'Int ' ,
84
84
);
85
85
86
86
private static $ belongs_many_many = array (
87
87
'Groups ' => Group::class,
88
88
);
89
89
90
90
private static $ has_many = array (
91
- 'LoggedPasswords ' => MemberPassword::class,
91
+ 'LoggedPasswords ' => MemberPassword::class,
92
92
'RememberLoginHashes ' => RememberLoginHash::class,
93
93
);
94
94
@@ -312,7 +312,7 @@ public function checkPassword($password)
312
312
break ;
313
313
}
314
314
}
315
- return $ result ;
315
+ return $ result ;
316
316
}
317
317
318
318
/**
@@ -521,10 +521,9 @@ public static function logged_in_session_exists()
521
521
'This method is deprecated and now does not add value. Please use Security::getCurrentUser() '
522
522
);
523
523
524
- if ($ member = Security::getCurrentUser ()) {
525
- if ($ member && $ member ->exists ()) {
526
- return true ;
527
- }
524
+ $ member = Security::getCurrentUser ();
525
+ if ($ member && $ member ->exists ()) {
526
+ return true ;
528
527
}
529
528
530
529
return false ;
@@ -655,7 +654,7 @@ public static function member_from_autologinhash($hash, $login = false)
655
654
{
656
655
/** @var Member $member */
657
656
$ member = static ::get ()->filter ([
658
- 'AutoLoginHash ' => $ hash ,
657
+ 'AutoLoginHash ' => $ hash ,
659
658
'AutoLoginExpired:GreaterThan ' => DBDatetime::now ()->getValue (),
660
659
])->first ();
661
660
@@ -799,6 +798,7 @@ public static function currentUser()
799
798
* @param Member|null|int $member Member or member ID to log in as.
800
799
* Set to null or 0 to act as a logged out user.
801
800
* @param callable $callback
801
+ * @return mixed Result of $callback
802
802
*/
803
803
public static function actAs ($ member , $ callback )
804
804
{
@@ -831,11 +831,11 @@ public static function currentUserID()
831
831
'This method is deprecated. Please use Security::getCurrentUser() or an IdentityStore '
832
832
);
833
833
834
- if ($ member = Security::getCurrentUser ()) {
834
+ $ member = Security::getCurrentUser ();
835
+ if ($ member ) {
835
836
return $ member ->ID ;
836
- } else {
837
- return 0 ;
838
837
}
838
+ return 0 ;
839
839
}
840
840
841
841
/**
@@ -892,8 +892,8 @@ public function onBeforeWrite()
892
892
'Can \'t overwrite existing member #{id} with identical identifier ({name} = {value})) ' ,
893
893
'Values in brackets show "fieldname = value", usually denoting an existing email address ' ,
894
894
array (
895
- 'id ' => $ existingRecord ->ID ,
896
- 'name ' => $ identifierField ,
895
+ 'id ' => $ existingRecord ->ID ,
896
+ 'name ' => $ identifierField ,
897
897
'value ' => $ this ->$ identifierField
898
898
)
899
899
));
@@ -912,7 +912,11 @@ public function onBeforeWrite()
912
912
->setHTMLTemplate ('SilverStripe \\Control \\Email \\ChangePasswordEmail ' )
913
913
->setData ($ this )
914
914
->setTo ($ this ->Email )
915
- ->setSubject (_t (__CLASS__ . '.SUBJECTPASSWORDCHANGED ' , "Your password has been changed " , 'Email subject ' ))
915
+ ->setSubject (_t (
916
+ __CLASS__ . '.SUBJECTPASSWORDCHANGED ' ,
917
+ "Your password has been changed " ,
918
+ 'Email subject '
919
+ ))
916
920
->send ();
917
921
}
918
922
@@ -973,17 +977,26 @@ protected function deletePasswordLogs()
973
977
* @return bool True if the change can be accepted
974
978
*/
975
979
public function onChangeGroups ($ ids )
980
+ {
981
+ // Ensure none of these match disallowed list
982
+ $ disallowedGroupIDs = $ this ->disallowedGroups ();
983
+ return count (array_intersect ($ ids , $ disallowedGroupIDs )) == 0 ;
984
+ }
985
+
986
+ /**
987
+ * List of group IDs this user is disallowed from
988
+ *
989
+ * @return int[] List of group IDs
990
+ */
991
+ protected function disallowedGroups ()
976
992
{
977
993
// unless the current user is an admin already OR the logged in user is an admin
978
994
if (Permission::check ('ADMIN ' ) || Permission::checkMember ($ this , 'ADMIN ' )) {
979
- return true ;
995
+ return [] ;
980
996
}
981
997
982
- // If there are no admin groups in this set then it's ok
983
- $ adminGroups = Permission::get_groups_by_permission ('ADMIN ' );
984
- $ adminGroupIDs = ($ adminGroups ) ? $ adminGroups ->column ('ID ' ) : array ();
985
-
986
- return count (array_intersect ($ ids , $ adminGroupIDs )) == 0 ;
998
+ // Non-admins may not belong to admin groups
999
+ return Permission::get_groups_by_permission ('ADMIN ' )->column ('ID ' );
987
1000
}
988
1001
989
1002
@@ -1159,7 +1172,7 @@ public static function get_title_sql()
1159
1172
if (!$ format ) {
1160
1173
$ format = [
1161
1174
'columns ' => ['Surname ' , 'FirstName ' ],
1162
- 'sep ' => ' ' ,
1175
+ 'sep ' => ' ' ,
1163
1176
];
1164
1177
}
1165
1178
@@ -1287,7 +1300,7 @@ public function Groups()
1287
1300
}
1288
1301
1289
1302
/**
1290
- * @return ManyManyList
1303
+ * @return ManyManyList|UnsavedRelationList
1291
1304
*/
1292
1305
public function DirectGroups ()
1293
1306
{
@@ -1468,8 +1481,14 @@ public function getCMSFields()
1468
1481
$ fields ->removeByName ('RememberLoginHashes ' );
1469
1482
1470
1483
if (Permission::check ('EDIT_PERMISSIONS ' )) {
1484
+ // Filter allowed groups
1485
+ $ groups = Group::get ();
1486
+ $ disallowedGroupIDs = $ this ->disallowedGroups ();
1487
+ if ($ disallowedGroupIDs ) {
1488
+ $ groups = $ groups ->exclude ('ID ' , $ disallowedGroupIDs );
1489
+ }
1471
1490
$ groupsMap = array ();
1472
- foreach (Group:: get () as $ group ) {
1491
+ foreach ($ groups as $ group ) {
1473
1492
// Listboxfield values are escaped, use ASCII char instead of »
1474
1493
$ groupsMap [$ group ->ID ] = $ group ->getBreadcrumbs (' > ' );
1475
1494
}
@@ -1524,7 +1543,11 @@ public function fieldLabels($includerelations = true)
1524
1543
/** @skipUpgrade */
1525
1544
$ labels ['Email ' ] = _t (__CLASS__ . '.EMAIL ' , 'Email ' );
1526
1545
$ labels ['Password ' ] = _t (__CLASS__ . '.db_Password ' , 'Password ' );
1527
- $ labels ['PasswordExpiry ' ] = _t (__CLASS__ . '.db_PasswordExpiry ' , 'Password Expiry Date ' , 'Password expiry date ' );
1546
+ $ labels ['PasswordExpiry ' ] = _t (
1547
+ __CLASS__ . '.db_PasswordExpiry ' ,
1548
+ 'Password Expiry Date ' ,
1549
+ 'Password expiry date '
1550
+ );
1528
1551
$ labels ['LockedOutUntil ' ] = _t (__CLASS__ . '.db_LockedOutUntil ' , 'Locked out until ' , 'Security related date ' );
1529
1552
$ labels ['Locale ' ] = _t (__CLASS__ . '.db_Locale ' , 'Interface Locale ' );
1530
1553
if ($ includerelations ) {
@@ -1673,8 +1696,8 @@ public function validate()
1673
1696
*
1674
1697
* This method will encrypt the password prior to writing.
1675
1698
*
1676
- * @param string $password Cleartext password
1677
- * @param bool $write Whether to write the member afterwards
1699
+ * @param string $password Cleartext password
1700
+ * @param bool $write Whether to write the member afterwards
1678
1701
* @return ValidationResult
1679
1702
*/
1680
1703
public function changePassword ($ password , $ write = true )
0 commit comments