package ldapSync /* this file contains functions to sync ldap users and groups to the database */ import ( "fmt" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/forms" "github.com/pocketbase/pocketbase/models" "gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger" ) // upsertLDAPGroup This function creates / updates a record in the ldap groups table func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error { // find ldapGroups table collection, err := app.Dao().FindCollectionByNameOrId(ldapGroupsTableName) if err != nil { return err } var record *models.Record // if record exists, update it if res, _ := app.Dao().FindFirstRecordByFilter( ldapGroupsTableName, "gidNumber = {:gidNumber}", dbx.Params{"gidNumber": ldapGroup.gidNumber}, ); res != nil { record = res } else { // if record does not exist, create it record = models.NewRecord(collection) } form := forms.NewRecordUpsert(app, record) var groups []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) } else { logger.LogErrorF("unable to find %s.memberOf: %s", ldapGroup.cn, groupDn) } } // load data err = form.LoadData(map[string]any{ "gidNumber": ldapGroup.gidNumber, "cn": ldapGroup.cn, "dn": ldapGroup.dn, "description": ldapGroup.description, "memberOf": groups, }) if err != nil { return err } // validate and submit (internally it calls app.Dao().SaveRecord(record) in a transaction) if err := form.Submit(); err != nil { return fmt.Errorf("failed to upsert group with dn: %s - %w", ldapGroup.dn, err) } return nil } // upsertLDAPUser This function creates / updates a record in the ldap users table func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error { // find ldapUsers table collection, err := app.Dao().FindCollectionByNameOrId(ldapUsersTableName) if err != nil { return err } var record *models.Record // if record exists, update it if res, _ := app.Dao().FindFirstRecordByFilter( ldapUsersTableName, "uidNumber = {:uidNumber}", dbx.Params{"uidNumber": ldapUser.uidNumber}, ); res != nil { record = res } else { // if record does not exist, create it record = models.NewRecord(collection) } accountExpires, _ := ldapTimeToUnixTime(ldapUser.accountExpires) var groups []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) } else { logger.LogErrorF("unable to find %s.memberOf: %s", ldapUser.cn, groupDn) } } record.Set("uidNumber", ldapUser.uidNumber) record.Set("givenName", ldapUser.givenName) record.Set("sn", ldapUser.sn) record.Set("username", ldapUser.cn) record.Set("accountExpires", accountExpires) record.Set("email", ldapUser.mail) record.Set("emailVisibility", false) record.Set("verified", true) record.Set("dn", ldapUser.dn) record.Set("cn", ldapUser.cn) record.Set("memberOf", groups) record.RefreshTokenKey() if err := app.Dao().SaveRecord(record); err != nil { return fmt.Errorf("failed to upsert user with dn: %s - %w", ldapUser.dn, err) } return nil } func GetLdapGroupByDN(app *pocketbase.PocketBase, dn string) (*models.Record, error) { return app.Dao().FindFirstRecordByFilter( ldapGroupsTableName, "dn = {:dn}", dbx.Params{"dn": dn}, ) } func GetLdapUserByCN(app *pocketbase.PocketBase, cn string) (*models.Record, error) { return app.Dao().FindFirstRecordByFilter( ldapUsersTableName, "cn = {:cn}", dbx.Params{"cn": cn}, ) }