diff --git a/ldapSync/db.go b/ldapSync/db.go index 1fd7fdf..488fe8c 100644 --- a/ldapSync/db.go +++ b/ldapSync/db.go @@ -27,8 +27,8 @@ func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error { // if record exists, update it if res, _ := app.Dao().FindFirstRecordByFilter( ldapGroupsTableName, - "id = {:id}", - dbx.Params{"id": ldapGroup.id}, + "objectGUID = {:objectGUID}", + dbx.Params{"objectGUID": ldapGroup.objectGUID}, ); res != nil { record = res } else { // if record does not exist, create it @@ -37,13 +37,13 @@ func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error { form := forms.NewRecordUpsert(app, record) - var groups []string + var memberOfGroupIds []string // get group ids from group dns for _, groupDn := range ldapGroup.memberOf { group, err := GetLdapGroupByDN(app, groupDn) if err == nil { - groups = append(groups, group.Id) + memberOfGroupIds = append(memberOfGroupIds, group.Id) } else { logger.LogErrorF("unable to find %s.memberOf: %s", ldapGroup.cn, groupDn) } @@ -51,11 +51,11 @@ func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error { // load data err = form.LoadData(map[string]any{ - "id": ldapGroup.id, + "objectGUID": ldapGroup.objectGUID, "cn": ldapGroup.cn, "dn": ldapGroup.dn, "description": ldapGroup.description, - "memberOf": groups, + "memberOf": memberOfGroupIds, }) if err != nil { return err @@ -83,8 +83,8 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error { // if record exists, update it if res, _ := app.Dao().FindFirstRecordByFilter( ldapUsersTableName, - "id = {:id}", - dbx.Params{"id": ldapUser.id}, + "objectGUID = {:objectGUID}", + dbx.Params{"objectGUID": ldapUser.objectGUID}, ); res != nil { record = res } else { // if record does not exist, create it @@ -99,19 +99,19 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error { accountExpires, _ := ldapTimeToUnixTime(ldapUser.accountExpires) - var groups []string + var memberOfGroupIds []string // get group ids from group dns for _, groupDn := range ldapUser.memberOf { group, err := GetLdapGroupByDN(app, groupDn) if err == nil { - groups = append(groups, group.Id) + memberOfGroupIds = append(memberOfGroupIds, group.Id) } else { logger.LogErrorF("unable to find %s.memberOf: %s", ldapUser.cn, groupDn) } } - record.Set("id", ldapUser.id) + record.Set("objectGUID", ldapUser.objectGUID) record.Set("givenName", ldapUser.givenName) record.Set("sn", ldapUser.sn) record.Set("username", ldapUser.cn) @@ -121,7 +121,7 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error { record.Set("verified", true) record.Set("dn", ldapUser.dn) record.Set("cn", ldapUser.cn) - record.Set("memberOf", groups) + record.Set("memberOf", memberOfGroupIds) if err := app.Dao().SaveRecord(record); err != nil { return fmt.Errorf("failed to upsert user with dn: %s - %w", ldapUser.dn, err) @@ -157,3 +157,37 @@ func GetLdapUserByCN(app *pocketbase.PocketBase, cn string) (*models.Record, err } return record, nil } + +// GetLdapGroupByObjectGUID This function returns a record from the ldap groups table by objectGUID. +// It also expands the memberOf field. +func GetLdapGroupByObjectGUID(app *pocketbase.PocketBase, objectGUID string) (*models.Record, error) { + record, err := app.Dao().FindFirstRecordByFilter( + ldapGroupsTableName, + "objectGUID = {:objectGUID}", + dbx.Params{"objectGUID": objectGUID}, + ) + if err != nil { + return nil, err + } + if errs := app.Dao().ExpandRecord(record, []string{"memberOf"}, nil); len(errs) > 0 { + return nil, fmt.Errorf("ldap group - failed to expand: %v", errs) + } + return record, nil +} + +// GetLdapUserByObjectGUID This function returns a record from the ldap users table by objectGUID. +// It also expands the memberOf field. +func GetLdapUserByObjectGUID(app *pocketbase.PocketBase, objectGUID string) (*models.Record, error) { + record, err := app.Dao().FindFirstRecordByFilter( + ldapUsersTableName, + "objectGUID = {:objectGUID}", + dbx.Params{"objectGUID": objectGUID}, + ) + if err != nil { + return nil, err + } + if errs := app.Dao().ExpandRecord(record, []string{"memberOf"}, nil); len(errs) > 0 { + return nil, fmt.Errorf("ldap user - failed to expand: %v", errs) + } + return record, nil +} diff --git a/ldapSync/ldapSync.go b/ldapSync/ldapSync.go index 3602490..78dba3c 100644 --- a/ldapSync/ldapSync.go +++ b/ldapSync/ldapSync.go @@ -33,7 +33,9 @@ func getObjectGUID(entry *ldap.Entry) (string, error) { if err != nil { return "", err } - return u.String()[:15], nil // only use the first 15 characters of the uuid + + // only use the first 15 characters of the uuid and remove all slashes + return u.String(), nil } // upsertLDAPGroup This function creates / updates a record in the ldap groups table @@ -63,14 +65,14 @@ func syncLdapGroups(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResul for _, entry := range groupsFoundInLdap.Entries { - var id, e = getObjectGUID(entry) + var objectGUID, e = getObjectGUID(entry) if e != nil { errors = append(errors, fmt.Errorf("unable to get objectGUID for group with dn: %s - %s", entry.DN, e)) } err := upsertLDAPGroup(app, &LDAPGroup{ - id: id, + objectGUID: objectGUID, description: entry.GetAttributeValue("description"), dn: entry.DN, cn: entry.GetAttributeValue("cn"), @@ -151,7 +153,7 @@ func syncLdapUsers(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResult for _, entry := range usersFoundInLdap.Entries { - var id, e = getObjectGUID(entry) + var objectGUID, e = getObjectGUID(entry) if e != nil { errors = append(errors, fmt.Errorf("unable to get objectGUID for user with dn: %s - %s", entry.DN, e)) @@ -161,7 +163,7 @@ func syncLdapUsers(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResult givenName: entry.GetAttributeValue("givenName"), sn: entry.GetAttributeValue("sn"), accountExpires: entry.GetAttributeValue("accountExpires"), - id: id, + objectGUID: objectGUID, mail: entry.GetAttributeValue("mail"), dn: entry.DN, cn: entry.GetAttributeValue("cn"), diff --git a/ldapSync/models.go b/ldapSync/models.go index 77c5d55..4623fa6 100644 --- a/ldapSync/models.go +++ b/ldapSync/models.go @@ -1,12 +1,11 @@ package ldapSync type LDAPUser struct { - id string - givenName string - sn string - accountExpires string - mail string - + objectGUID string + givenName string + sn string + accountExpires string + mail string dn string cn string msSFU30NisDomain string // must be STUVE @@ -14,9 +13,8 @@ type LDAPUser struct { } type LDAPGroup struct { - id string - description string - + objectGUID string + description string dn string cn string msSFU30NisDomain string diff --git a/ldapSync/tables.go b/ldapSync/tables.go index 675f84b..9207660 100644 --- a/ldapSync/tables.go +++ b/ldapSync/tables.go @@ -55,9 +55,17 @@ func createLDAPGroupsTable(app *pocketbase.PocketBase) error { Required: true, }) + // add objectGUID field + form.Schema.AddField(&schema.SchemaField{ + Name: "objectGUID", + Type: schema.FieldTypeText, + Required: true, + }) + // create index on cn form.Indexes = types.JsonArray[string]{ - "CREATE UNIQUE INDEX idx_ldapGroups ON " + ldapGroupsTableName + " (cn, dn)", + "CREATE UNIQUE INDEX idx_ldapGroups_cn ON " + ldapGroupsTableName + " (cn)", + "CREATE UNIQUE INDEX idx_ldapGroups_objectGUID ON " + ldapSyncLogsTableName + " (objectGUID)", } // validate and submit (internally it calls app.Dao().SaveCollection(collection) in a transaction) @@ -130,6 +138,13 @@ func createLDAPUsersTable(app *pocketbase.PocketBase) error { Presentable: true, }) + // add objectGUID field + form.Schema.AddField(&schema.SchemaField{ + Name: "objectGUID", + Type: schema.FieldTypeText, + Required: true, + }) + // add distinguished name field form.Schema.AddField(&schema.SchemaField{ Name: "dn", @@ -171,7 +186,8 @@ func createLDAPUsersTable(app *pocketbase.PocketBase) error { // create index on username form.Indexes = types.JsonArray[string]{ - "CREATE UNIQUE INDEX idx_ldapUsers ON " + ldapGroupsTableName + " (cn, dn)", + "CREATE UNIQUE INDEX idx_ldapUsers_cn ON " + ldapGroupsTableName + " (cn)", + "CREATE UNIQUE INDEX idx_ldapUsers_objectGUID ON " + ldapSyncLogsTableName + " (objectGUID)", } return form.Submit()