stuve-it-backend/ldapSync/db.go

212 lines
6.2 KiB
Go
Raw Permalink Normal View History

2023-10-26 20:34:59 +00:00
package ldapSync
/*
this file contains functions to sync ldap users and groups to the database
*/
import (
"fmt"
"git.stuve.uni-ulm.de/stuve-it/stuve-it-backend/logger"
2023-10-26 20:34:59 +00:00
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/forms"
"github.com/pocketbase/pocketbase/models"
"os"
"strings"
2023-10-26 20:34:59 +00:00
)
// 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,
"objectGUID = {:objectGUID}",
dbx.Params{"objectGUID": ldapGroup.objectGUID},
2023-10-26 20:34:59 +00:00
); res != nil {
record = res
} else { // if record does not exist, create it
record = models.NewRecord(collection)
}
form := forms.NewRecordUpsert(app, record)
var memberOfGroupIds []string
2023-10-26 20:34:59 +00:00
// get group ids from group dns
for _, groupDn := range ldapGroup.memberOf {
group, err := GetLdapGroupByDN(app, groupDn)
if err == nil {
memberOfGroupIds = append(memberOfGroupIds, group.Id)
2023-10-26 20:34:59 +00:00
} else {
logger.LogErrorF("unable to find %s.memberOf: %s", ldapGroup.cn, groupDn)
}
}
// load data
err = form.LoadData(map[string]any{
"objectGUID": ldapGroup.objectGUID,
2023-10-26 20:34:59 +00:00
"cn": ldapGroup.cn,
"dn": ldapGroup.dn,
"description": ldapGroup.description,
"memberOf": memberOfGroupIds,
2023-10-26 20:34:59 +00:00
})
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,
"objectGUID = {:objectGUID}",
dbx.Params{"objectGUID": ldapUser.objectGUID},
2023-10-26 20:34:59 +00:00
); res != nil {
record = res
} else { // if record does not exist, create it
record = models.NewRecord(collection)
2023-11-20 15:32:32 +00:00
// refresh token key only if new record is created
// if record is updated, the token key should not be changed because it is used to authenticate the user
// if the token key is changed, the user will be logged out
if err := record.RefreshTokenKey(); err != nil {
return err
}
2023-10-26 20:34:59 +00:00
}
// calculate accountExpires
2023-10-26 20:34:59 +00:00
accountExpires, _ := ldapTimeToUnixTime(ldapUser.accountExpires)
var memberOfGroupIds []string
var isAdmin bool
2023-10-26 20:34:59 +00:00
// get group ids from group dns
for _, groupDn := range ldapUser.memberOf {
// get group by dn
2023-10-26 20:34:59 +00:00
group, err := GetLdapGroupByDN(app, groupDn)
// check if error
if err != nil {
2023-10-26 20:34:59 +00:00
logger.LogErrorF("unable to find %s.memberOf: %s", ldapUser.cn, groupDn)
continue
}
// check if user is in admin group
if strings.ToLower(group.Get("dn").(string)) == strings.ToLower(os.Getenv("LDAP_ADMIN_GROUP_DN")) {
isAdmin = true
2023-10-26 20:34:59 +00:00
}
// add group id to memberOfGroupIds
memberOfGroupIds = append(memberOfGroupIds, group.Id)
2023-10-26 20:34:59 +00:00
}
// set data
record.Set("objectGUID", ldapUser.objectGUID)
2023-10-26 20:34:59 +00:00
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", memberOfGroupIds)
record.Set("REALM", ldapUser.REALM)
record.Set("isAdmin", isAdmin)
2023-10-26 20:34:59 +00:00
if err := app.Dao().SaveRecord(record); err != nil {
return fmt.Errorf("failed to upsert user with dn: %s - %w", ldapUser.dn, err)
}
return nil
}
2023-11-20 15:32:32 +00:00
// GetLdapGroupByDN This function returns a record from the ldap groups table by dn. It also expands the memberOf field.
2023-10-26 20:34:59 +00:00
func GetLdapGroupByDN(app *pocketbase.PocketBase, dn string) (*models.Record, error) {
2023-11-20 15:32:32 +00:00
record, err := app.Dao().FindFirstRecordByFilter(
2023-10-26 20:34:59 +00:00
ldapGroupsTableName,
"dn = {:dn}",
dbx.Params{"dn": dn},
)
2023-11-20 15:32:32 +00:00
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
2023-10-26 20:34:59 +00:00
}
2023-11-20 15:32:32 +00:00
// GetLdapUserByCN This function returns a record from the ldap users table by cn. It also expands the memberOf field.
2023-10-26 20:34:59 +00:00
func GetLdapUserByCN(app *pocketbase.PocketBase, cn string) (*models.Record, error) {
2023-11-20 15:32:32 +00:00
record, err := app.Dao().FindAuthRecordByUsername(ldapUsersTableName, cn)
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
2023-10-26 20:34:59 +00:00
}
// 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
}