Skip to content

Commit 9b7043a

Browse files
committed
Add job to syncronise users with LDAP
1 parent 38a0323 commit 9b7043a

File tree

4 files changed

+160
-4
lines changed

4 files changed

+160
-4
lines changed

conf/app.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,11 @@ SCHEDULE = @every 24h
439439
; Archives created more than OLDER_THAN ago are subject to deletion
440440
OLDER_THAN = 24h
441441

442+
; Synchronize external user data
443+
[cron.sync_external_users]
444+
SCHEDULE = @every 24h
445+
UPDATE_EXISTING = true
446+
442447
[git]
443448
; Disables highlight of added and removed changes
444449
DISABLE_DIFF_HIGHLIGHT = false

models/user.go

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ const (
5050
UserTypeOrganization
5151
)
5252

53+
const syncExternalUsers = "sync_external_users"
54+
5355
var (
5456
// ErrUserNotKeyOwner user does not own this key error
5557
ErrUserNotKeyOwner = errors.New("User does not own this public key")
@@ -826,10 +828,10 @@ func ChangeUserName(u *User, newUserName string) (err error) {
826828
if err = x.
827829
Where("owner_id=?", u.ID).
828830
Iterate(new(Repository), func(idx int, bean interface{}) error {
829-
repo := bean.(*Repository)
830-
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalUncycloPath())
831-
return nil
832-
}); err != nil {
831+
repo := bean.(*Repository)
832+
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalUncycloPath())
833+
return nil
834+
}); err != nil {
833835
return fmt.Errorf("Delete repository wiki local copy: %v", err)
834836
}
835837

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

modules/cron/cron.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ func NewContext() {
6666
go models.DeleteOldRepositoryArchives()
6767
}
6868
}
69+
if setting.Cron.SyncExternalUsers.Enabled {
70+
entry, err = c.AddFunc("Synchronize external users", setting.Cron.SyncExternalUsers.Schedule, models.SyncExternalUsers)
71+
if err != nil {
72+
log.Fatal(4, "Cron[Synchronize external users]: %v", err)
73+
}
74+
if setting.Cron.SyncExternalUsers.RunAtStart {
75+
entry.Prev = time.Now()
76+
entry.ExecTimes++
77+
go models.SyncExternalUsers()
78+
}
79+
}
6980
c.Start()
7081
}
7182

modules/setting/setting.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ var (
336336
Schedule string
337337
OlderThan time.Duration
338338
} `ini:"cron.archive_cleanup"`
339+
SyncExternalUsers struct {
340+
Enabled bool
341+
RunAtStart bool
342+
Schedule string
343+
UpdateExisting bool
344+
} `ini:"cron.sync_external_users"`
339345
}{
340346
UpdateMirror: struct {
341347
Enabled bool
@@ -379,6 +385,17 @@ var (
379385
Schedule: "@every 24h",
380386
OlderThan: 24 * time.Hour,
381387
},
388+
SyncExternalUsers: struct {
389+
Enabled bool
390+
RunAtStart bool
391+
Schedule string
392+
UpdateExisting bool
393+
}{
394+
Enabled: true,
395+
RunAtStart: false,
396+
Schedule: "@every 24h",
397+
UpdateExisting: true,
398+
},
382399
}
383400

384401
// Git settings

0 commit comments

Comments
 (0)