@@ -50,6 +50,8 @@ const (
5050 UserTypeOrganization
5151)
5252
53+ const syncExternalUsers = "sync_external_users"
54+
5355var (
5456 // ErrUserNotKeyOwner user does not own this key error
5557 ErrUserNotKeyOwner = errors .New ("User does not own this public key" )
@@ -1322,3 +1324,128 @@ func GetWatchedRepos(userID int64, private bool) ([]*Repository, error) {
13221324 }
13231325 return repos , nil
13241326}
1327+
1328+ // SyncExternalUsers is used to synchronize users with external authorization source
1329+ func SyncExternalUsers () {
1330+ if taskStatusTable .IsRunning (syncExternalUsers ) {
1331+ return
1332+ }
1333+ taskStatusTable .Start (syncExternalUsers )
1334+ defer taskStatusTable .Stop (syncExternalUsers )
1335+
1336+ log .Trace ("Doing: SyncExternalUsers" )
1337+
1338+ ls , err := LoginSources ()
1339+ if err != nil {
1340+ log .Error (4 , "SyncExternalUsers: %v" , err )
1341+ return
1342+ }
1343+
1344+ updateExisting := setting .Cron .SyncExternalUsers .UpdateExisting
1345+
1346+ for _ , s := range ls {
1347+ if ! s .IsActived || ! s .IsSyncEnabled {
1348+ continue
1349+ }
1350+ if s .IsLDAP () {
1351+ log .Trace ("Doing: SyncExternalUsers[%s]" , s .Name )
1352+
1353+ var existingUsers []int64
1354+
1355+ // Find all users with this login type
1356+ var users []User
1357+ x .Where ("login_type = ?" , LoginLDAP ).
1358+ And ("login_source = ?" , s .ID ).
1359+ Find (& users )
1360+
1361+ sr := s .LDAP ().SearchEntries ()
1362+
1363+ for _ , su := range sr {
1364+ if len (su .Username ) == 0 {
1365+ continue
1366+ }
1367+
1368+ if len (su .Mail ) == 0 {
1369+ su .Mail = fmt .Sprintf ("%s@localhost" , su .Username )
1370+ }
1371+
1372+ var usr * User
1373+ // Search for existing user
1374+ for _ , du := range users {
1375+ if du .LowerName == strings .ToLower (su .Username ) {
1376+ usr = & du
1377+ break
1378+ }
1379+ }
1380+
1381+ fullName := composeFullName (su .Name , su .Surname , su .Username )
1382+ // If no existing user found, create one
1383+ if usr == nil {
1384+ log .Trace ("SyncExternalUsers[%s]: Creating user %s" , s .Name , su .Username )
1385+
1386+ usr = & User {
1387+ LowerName : strings .ToLower (su .Username ),
1388+ Name : su .Username ,
1389+ FullName : fullName ,
1390+ LoginType : s .Type ,
1391+ LoginSource : s .ID ,
1392+ LoginName : su .Username ,
1393+ Email : su .Mail ,
1394+ IsAdmin : su .IsAdmin ,
1395+ IsActive : true ,
1396+ }
1397+
1398+ err = CreateUser (usr )
1399+ if err != nil {
1400+ log .Error (4 , "SyncExternalUsers[%s]: Error creating user %s: %v" , s .Name , su .Username , err )
1401+ }
1402+ } else if updateExisting {
1403+ existingUsers = append (existingUsers , usr .ID )
1404+ // Check if user data has changed
1405+ if (len (s .LDAP ().AdminFilter ) > 0 && usr .IsAdmin != su .IsAdmin ) ||
1406+ strings .ToLower (usr .Email ) != strings .ToLower (su .Mail ) ||
1407+ usr .FullName != fullName ||
1408+ ! usr .IsActive {
1409+
1410+ log .Trace ("SyncExternalUsers[%s]: Updating user %s" , s .Name , usr .Name )
1411+
1412+ usr .FullName = fullName
1413+ usr .Email = su .Mail
1414+ // Change existing admin flag only if AdminFilter option is set
1415+ if len (s .LDAP ().AdminFilter ) > 0 {
1416+ usr .IsAdmin = su .IsAdmin
1417+ }
1418+ usr .IsActive = true
1419+
1420+ err = UpdateUser (usr )
1421+ if err != nil {
1422+ log .Error (4 , "SyncExternalUsers[%s]: Error updating user %s: %v" , s .Name , usr .Name , err )
1423+ }
1424+ }
1425+ }
1426+ }
1427+
1428+ // Deactivate users not present in LDAP
1429+ if updateExisting {
1430+ for _ , usr := range users {
1431+ found := false
1432+ for _ , uid := range existingUsers {
1433+ if usr .ID == uid {
1434+ found = true
1435+ break
1436+ }
1437+ }
1438+ if ! found {
1439+ log .Trace ("SyncExternalUsers[%s]: Deactivating user %s" , s .Name , usr .Name )
1440+
1441+ usr .IsActive = false
1442+ err = UpdateUser (& usr )
1443+ if err != nil {
1444+ log .Error (4 , "SyncExternalUsers[%s]: Error deactivating user %s: %v" , s .Name , usr .Name , err )
1445+ }
1446+ }
1447+ }
1448+ }
1449+ }
1450+ }
1451+ }
0 commit comments