mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 14:50:55 +03:00
EventManager: add IDP login trigger and check account action
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -56,6 +57,12 @@ const (
|
||||
maxAttachmentsSize = int64(10 * 1024 * 1024)
|
||||
)
|
||||
|
||||
// Supported IDP login events
|
||||
const (
|
||||
IDPLoginUser = "IDP login user"
|
||||
IDPLoginAdmin = "IDP login admin"
|
||||
)
|
||||
|
||||
var (
|
||||
// eventManager handle the supported event rules actions
|
||||
eventManager eventRulesContainer
|
||||
@@ -90,6 +97,11 @@ func HandleCertificateEvent(params EventParams) {
|
||||
eventManager.handleCertificateEvent(params)
|
||||
}
|
||||
|
||||
// HandleIDPLoginEvent executes actions defined for a successful login from an Identity Provider
|
||||
func HandleIDPLoginEvent(params EventParams, customFields *map[string]any) (*dataprovider.User, *dataprovider.Admin, error) {
|
||||
return eventManager.handleIDPLoginEvent(params, customFields)
|
||||
}
|
||||
|
||||
// eventRulesContainer stores event rules by trigger
|
||||
type eventRulesContainer struct {
|
||||
sync.RWMutex
|
||||
@@ -99,6 +111,7 @@ type eventRulesContainer struct {
|
||||
Schedules []dataprovider.EventRule
|
||||
IPBlockedEvents []dataprovider.EventRule
|
||||
CertificateEvents []dataprovider.EventRule
|
||||
IPDLoginEvents []dataprovider.EventRule
|
||||
schedulesMapping map[string][]cron.EntryID
|
||||
concurrencyGuard chan struct{}
|
||||
}
|
||||
@@ -168,6 +181,15 @@ func (r *eventRulesContainer) removeRuleInternal(name string) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for idx := range r.IPDLoginEvents {
|
||||
if r.IPDLoginEvents[idx].Name == name {
|
||||
lastIdx := len(r.IPDLoginEvents) - 1
|
||||
r.IPDLoginEvents[idx] = r.IPDLoginEvents[lastIdx]
|
||||
r.IPDLoginEvents = r.IPDLoginEvents[:lastIdx]
|
||||
eventManagerLog(logger.LevelDebug, "removed rule %q from IDP login events", name)
|
||||
return
|
||||
}
|
||||
}
|
||||
for idx := range r.Schedules {
|
||||
if r.Schedules[idx].Name == name {
|
||||
if schedules, ok := r.schedulesMapping[name]; ok {
|
||||
@@ -213,6 +235,9 @@ func (r *eventRulesContainer) addUpdateRuleInternal(rule dataprovider.EventRule)
|
||||
case dataprovider.EventTriggerCertificate:
|
||||
r.CertificateEvents = append(r.CertificateEvents, rule)
|
||||
eventManagerLog(logger.LevelDebug, "added rule %q to certificate events", rule.Name)
|
||||
case dataprovider.EventTriggerIDPLogin:
|
||||
r.IPDLoginEvents = append(r.IPDLoginEvents, rule)
|
||||
eventManagerLog(logger.LevelDebug, "added rule %q to IDP login events", rule.Name)
|
||||
case dataprovider.EventTriggerSchedule:
|
||||
for _, schedule := range rule.Conditions.Schedules {
|
||||
cronSpec := schedule.GetCronSpec()
|
||||
@@ -253,13 +278,27 @@ func (r *eventRulesContainer) loadRules() {
|
||||
r.addUpdateRuleInternal(rule)
|
||||
}
|
||||
}
|
||||
eventManagerLog(logger.LevelDebug, "event rules updated, fs events: %d, provider events: %d, schedules: %d, ip blocked events: %d, certificate events: %d",
|
||||
len(r.FsEvents), len(r.ProviderEvents), len(r.Schedules), len(r.IPBlockedEvents), len(r.CertificateEvents))
|
||||
eventManagerLog(logger.LevelDebug, "event rules updated, fs events: %d, provider events: %d, schedules: %d, ip blocked events: %d, certificate events: %d, IDP login events: %d",
|
||||
len(r.FsEvents), len(r.ProviderEvents), len(r.Schedules), len(r.IPBlockedEvents), len(r.CertificateEvents), len(r.IPDLoginEvents))
|
||||
|
||||
r.setLastLoadTime(modTime)
|
||||
}
|
||||
|
||||
func (r *eventRulesContainer) checkProviderEventMatch(conditions dataprovider.EventConditions, params EventParams) bool {
|
||||
func (*eventRulesContainer) checkIPDLoginEventMatch(conditions *dataprovider.EventConditions, params *EventParams) bool {
|
||||
switch conditions.IDPLoginEvent {
|
||||
case dataprovider.IDPLoginUser:
|
||||
if params.Event != IDPLoginUser {
|
||||
return false
|
||||
}
|
||||
case dataprovider.IDPLoginAdmin:
|
||||
if params.Event != IDPLoginAdmin {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return checkEventConditionPatterns(params.Name, conditions.Options.Names)
|
||||
}
|
||||
|
||||
func (*eventRulesContainer) checkProviderEventMatch(conditions *dataprovider.EventConditions, params *EventParams) bool {
|
||||
if !util.Contains(conditions.ProviderEvents, params.Event) {
|
||||
return false
|
||||
}
|
||||
@@ -275,7 +314,7 @@ func (r *eventRulesContainer) checkProviderEventMatch(conditions dataprovider.Ev
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *eventRulesContainer) checkFsEventMatch(conditions dataprovider.EventConditions, params EventParams) bool {
|
||||
func (*eventRulesContainer) checkFsEventMatch(conditions *dataprovider.EventConditions, params *EventParams) bool {
|
||||
if !util.Contains(conditions.FsEvents, params.Event) {
|
||||
return false
|
||||
}
|
||||
@@ -327,7 +366,7 @@ func (r *eventRulesContainer) handleFsEvent(params EventParams) (bool, error) {
|
||||
|
||||
var rulesWithSyncActions, rulesAsync []dataprovider.EventRule
|
||||
for _, rule := range r.FsEvents {
|
||||
if r.checkFsEventMatch(rule.Conditions, params) {
|
||||
if r.checkFsEventMatch(&rule.Conditions, ¶ms) {
|
||||
if err := rule.CheckActionsConsistency(""); err != nil {
|
||||
eventManagerLog(logger.LevelWarn, "rule %q skipped: %v, event %q",
|
||||
rule.Name, err, params.Event)
|
||||
@@ -361,6 +400,59 @@ func (r *eventRulesContainer) handleFsEvent(params EventParams) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *eventRulesContainer) handleIDPLoginEvent(params EventParams, customFields *map[string]any) (*dataprovider.User,
|
||||
*dataprovider.Admin, error,
|
||||
) {
|
||||
r.RLock()
|
||||
|
||||
var rulesWithSyncActions, rulesAsync []dataprovider.EventRule
|
||||
for _, rule := range r.IPDLoginEvents {
|
||||
if r.checkIPDLoginEventMatch(&rule.Conditions, ¶ms) {
|
||||
if err := rule.CheckActionsConsistency(""); err != nil {
|
||||
eventManagerLog(logger.LevelWarn, "rule %q skipped: %v, event %q",
|
||||
rule.Name, err, params.Event)
|
||||
continue
|
||||
}
|
||||
hasSyncActions := false
|
||||
for _, action := range rule.Actions {
|
||||
if action.Options.ExecuteSync {
|
||||
hasSyncActions = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if hasSyncActions {
|
||||
rulesWithSyncActions = append(rulesWithSyncActions, rule)
|
||||
} else {
|
||||
rulesAsync = append(rulesAsync, rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.RUnlock()
|
||||
|
||||
if len(rulesAsync) == 0 && len(rulesWithSyncActions) == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
params.addIDPCustomFields(customFields)
|
||||
if len(rulesWithSyncActions) > 1 {
|
||||
var ruleNames []string
|
||||
for _, r := range rulesWithSyncActions {
|
||||
ruleNames = append(ruleNames, r.Name)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("more than one account check action rules matches: %q", strings.Join(ruleNames, ","))
|
||||
}
|
||||
|
||||
if len(rulesAsync) > 0 {
|
||||
go executeAsyncRulesActions(rulesAsync, params)
|
||||
}
|
||||
|
||||
if len(rulesWithSyncActions) > 0 {
|
||||
return executeIDPAccountCheckRule(rulesWithSyncActions[0], params)
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// username is populated for user objects
|
||||
func (r *eventRulesContainer) handleProviderEvent(params EventParams) {
|
||||
r.RLock()
|
||||
@@ -368,7 +460,7 @@ func (r *eventRulesContainer) handleProviderEvent(params EventParams) {
|
||||
|
||||
var rules []dataprovider.EventRule
|
||||
for _, rule := range r.ProviderEvents {
|
||||
if r.checkProviderEventMatch(rule.Conditions, params) {
|
||||
if r.checkProviderEventMatch(&rule.Conditions, ¶ms) {
|
||||
if err := rule.CheckActionsConsistency(params.ObjectType); err == nil {
|
||||
rules = append(rules, rule)
|
||||
} else {
|
||||
@@ -452,6 +544,7 @@ type EventParams struct {
|
||||
IP string
|
||||
Role string
|
||||
Timestamp int64
|
||||
IDPCustomFields *map[string]string
|
||||
Object plugin.Renderer
|
||||
sender string
|
||||
updateStatusFromError bool
|
||||
@@ -474,10 +567,32 @@ func (p *EventParams) getACopy() *EventParams {
|
||||
retentionChecks = append(retentionChecks, executedCheck)
|
||||
}
|
||||
params.retentionChecks = retentionChecks
|
||||
if p.IDPCustomFields != nil {
|
||||
fields := make(map[string]string)
|
||||
for k, v := range *p.IDPCustomFields {
|
||||
fields[k] = v
|
||||
}
|
||||
params.IDPCustomFields = &fields
|
||||
}
|
||||
|
||||
return ¶ms
|
||||
}
|
||||
|
||||
func (p *EventParams) addIDPCustomFields(customFields *map[string]any) {
|
||||
if customFields == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fields := make(map[string]string)
|
||||
for k, v := range *customFields {
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
fields[k] = val
|
||||
}
|
||||
}
|
||||
p.IDPCustomFields = &fields
|
||||
}
|
||||
|
||||
// AddError adds a new error to the event params and update the status if needed
|
||||
func (p *EventParams) AddError(err error) {
|
||||
if err == nil {
|
||||
@@ -622,34 +737,41 @@ func (p *EventParams) getRetentionReportsAsMailAttachment() (*mail.File, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *EventParams) getStringReplacements(addObjectData bool) []string {
|
||||
func (*EventParams) getStringReplacement(val string, jsonEscaped bool) string {
|
||||
if jsonEscaped {
|
||||
return util.JSONEscape(val)
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []string {
|
||||
replacements := []string{
|
||||
"{{Name}}", p.Name,
|
||||
"{{Name}}", p.getStringReplacement(p.Name, jsonEscaped),
|
||||
"{{Event}}", p.Event,
|
||||
"{{Status}}", fmt.Sprintf("%d", p.Status),
|
||||
"{{VirtualPath}}", p.VirtualPath,
|
||||
"{{FsPath}}", p.FsPath,
|
||||
"{{VirtualTargetPath}}", p.VirtualTargetPath,
|
||||
"{{FsTargetPath}}", p.FsTargetPath,
|
||||
"{{ObjectName}}", p.ObjectName,
|
||||
"{{VirtualPath}}", p.getStringReplacement(p.VirtualPath, jsonEscaped),
|
||||
"{{FsPath}}", p.getStringReplacement(p.FsPath, jsonEscaped),
|
||||
"{{VirtualTargetPath}}", p.getStringReplacement(p.VirtualTargetPath, jsonEscaped),
|
||||
"{{FsTargetPath}}", p.getStringReplacement(p.FsTargetPath, jsonEscaped),
|
||||
"{{ObjectName}}", p.getStringReplacement(p.ObjectName, jsonEscaped),
|
||||
"{{ObjectType}}", p.ObjectType,
|
||||
"{{FileSize}}", fmt.Sprintf("%d", p.FileSize),
|
||||
"{{Elapsed}}", fmt.Sprintf("%d", p.Elapsed),
|
||||
"{{Protocol}}", p.Protocol,
|
||||
"{{IP}}", p.IP,
|
||||
"{{Role}}", p.Role,
|
||||
"{{Role}}", p.getStringReplacement(p.Role, jsonEscaped),
|
||||
"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
|
||||
"{{StatusString}}", p.getStatusString(),
|
||||
}
|
||||
if p.VirtualPath != "" {
|
||||
replacements = append(replacements, "{{VirtualDirPath}}", path.Dir(p.VirtualPath))
|
||||
replacements = append(replacements, "{{VirtualDirPath}}", p.getStringReplacement(path.Dir(p.VirtualPath), jsonEscaped))
|
||||
}
|
||||
if p.VirtualTargetPath != "" {
|
||||
replacements = append(replacements, "{{VirtualTargetDirPath}}", path.Dir(p.VirtualTargetPath))
|
||||
replacements = append(replacements, "{{TargetName}}", path.Base(p.VirtualTargetPath))
|
||||
replacements = append(replacements, "{{VirtualTargetDirPath}}", p.getStringReplacement(path.Dir(p.VirtualTargetPath), jsonEscaped))
|
||||
replacements = append(replacements, "{{TargetName}}", p.getStringReplacement(path.Base(p.VirtualTargetPath), jsonEscaped))
|
||||
}
|
||||
if len(p.errors) > 0 {
|
||||
replacements = append(replacements, "{{ErrorString}}", strings.Join(p.errors, ", "))
|
||||
replacements = append(replacements, "{{ErrorString}}", p.getStringReplacement(strings.Join(p.errors, ", "), jsonEscaped))
|
||||
} else {
|
||||
replacements = append(replacements, "{{ErrorString}}", "")
|
||||
}
|
||||
@@ -660,6 +782,11 @@ func (p *EventParams) getStringReplacements(addObjectData bool) []string {
|
||||
replacements[len(replacements)-1] = string(data)
|
||||
}
|
||||
}
|
||||
if p.IDPCustomFields != nil {
|
||||
for k, v := range *p.IDPCustomFields {
|
||||
replacements = append(replacements, fmt.Sprintf("{{IDPField%s}}", k), p.getStringReplacement(v, jsonEscaped))
|
||||
}
|
||||
}
|
||||
return replacements
|
||||
}
|
||||
|
||||
@@ -1060,7 +1187,7 @@ func getHTTPRuleActionEndpoint(c dataprovider.EventActionHTTPConfig, replacer *s
|
||||
}
|
||||
|
||||
func writeHTTPPart(m *multipart.Writer, part dataprovider.HTTPPart, h textproto.MIMEHeader,
|
||||
conn *BaseConnection, replacer *strings.Replacer, params *EventParams,
|
||||
conn *BaseConnection, replacer *strings.Replacer, params *EventParams, addObjectData bool,
|
||||
) error {
|
||||
partWriter, err := m.CreatePart(h)
|
||||
if err != nil {
|
||||
@@ -1068,7 +1195,14 @@ func writeHTTPPart(m *multipart.Writer, part dataprovider.HTTPPart, h textproto.
|
||||
return err
|
||||
}
|
||||
if part.Body != "" {
|
||||
_, err = partWriter.Write([]byte(replaceWithReplacer(part.Body, replacer)))
|
||||
cType := h.Get("Content-Type")
|
||||
if strings.Contains(strings.ToLower(cType), "application/json") {
|
||||
replacements := params.getStringReplacements(addObjectData, true)
|
||||
jsonReplacer := strings.NewReplacer(replacements...)
|
||||
_, err = partWriter.Write([]byte(replaceWithReplacer(part.Body, jsonReplacer)))
|
||||
} else {
|
||||
_, err = partWriter.Write([]byte(replaceWithReplacer(part.Body, replacer)))
|
||||
}
|
||||
if err != nil {
|
||||
eventManagerLog(logger.LevelError, "unable to write part %q, err: %v", part.Name, err)
|
||||
return err
|
||||
@@ -1095,8 +1229,8 @@ func writeHTTPPart(m *multipart.Writer, part dataprovider.HTTPPart, h textproto.
|
||||
return nil
|
||||
}
|
||||
|
||||
func getHTTPRuleActionBody(c dataprovider.EventActionHTTPConfig, replacer *strings.Replacer,
|
||||
cancel context.CancelFunc, user dataprovider.User, params *EventParams,
|
||||
func getHTTPRuleActionBody(c *dataprovider.EventActionHTTPConfig, replacer *strings.Replacer,
|
||||
cancel context.CancelFunc, user dataprovider.User, params *EventParams, addObjectData bool,
|
||||
) (io.ReadCloser, string, error) {
|
||||
var body io.ReadCloser
|
||||
if c.Method == http.MethodGet {
|
||||
@@ -1110,6 +1244,11 @@ func getHTTPRuleActionBody(c dataprovider.EventActionHTTPConfig, replacer *strin
|
||||
}
|
||||
return io.NopCloser(bytes.NewBuffer(data)), "", nil
|
||||
}
|
||||
if c.HasJSONBody() {
|
||||
replacements := params.getStringReplacements(addObjectData, true)
|
||||
jsonReplacer := strings.NewReplacer(replacements...)
|
||||
return io.NopCloser(bytes.NewBufferString(replaceWithReplacer(c.Body, jsonReplacer))), "", nil
|
||||
}
|
||||
return io.NopCloser(bytes.NewBufferString(replaceWithReplacer(c.Body, replacer))), "", nil
|
||||
}
|
||||
if len(c.Parts) > 0 {
|
||||
@@ -1154,7 +1293,7 @@ func getHTTPRuleActionBody(c dataprovider.EventActionHTTPConfig, replacer *strin
|
||||
for _, keyVal := range part.Headers {
|
||||
h.Set(keyVal.Key, replaceWithReplacer(keyVal.Value, replacer))
|
||||
}
|
||||
if err := writeHTTPPart(m, part, h, conn, replacer, params); err != nil {
|
||||
if err := writeHTTPPart(m, part, h, conn, replacer, params, addObjectData); err != nil {
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
@@ -1176,7 +1315,7 @@ func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params *EventPa
|
||||
addObjectData = c.HasObjectData()
|
||||
}
|
||||
|
||||
replacements := params.getStringReplacements(addObjectData)
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
endpoint, err := getHTTPRuleActionEndpoint(c, replacer)
|
||||
if err != nil {
|
||||
@@ -1193,7 +1332,7 @@ func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params *EventPa
|
||||
return err
|
||||
}
|
||||
}
|
||||
body, contentType, err := getHTTPRuleActionBody(c, replacer, cancel, user, params)
|
||||
body, contentType, err := getHTTPRuleActionBody(&c, replacer, cancel, user, params, addObjectData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1244,7 +1383,7 @@ func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params *E
|
||||
}
|
||||
}
|
||||
}
|
||||
replacements := params.getStringReplacements(addObjectData)
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
|
||||
args := make([]string, 0, len(c.Args))
|
||||
@@ -1277,7 +1416,7 @@ func executeEmailRuleAction(c dataprovider.EventActionEmailConfig, params *Event
|
||||
addObjectData = true
|
||||
}
|
||||
}
|
||||
replacements := params.getStringReplacements(addObjectData)
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
body := replaceWithReplacer(c.Body, replacer)
|
||||
subject := replaceWithReplacer(c.Subject, replacer)
|
||||
@@ -1825,7 +1964,7 @@ func executeFsRuleAction(c dataprovider.EventActionFilesystemConfig, conditions
|
||||
params *EventParams,
|
||||
) error {
|
||||
addObjectData := false
|
||||
replacements := params.getStringReplacements(addObjectData)
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
switch c.Type {
|
||||
case dataprovider.FilesystemActionRename:
|
||||
@@ -2207,6 +2346,71 @@ func executePwdExpirationCheckRuleAction(config dataprovider.EventActionPassword
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeAdminCheckAction(c *dataprovider.EventActionIDPAccountCheck, params *EventParams) (*dataprovider.Admin, error) {
|
||||
admin, err := dataprovider.AdminExists(params.Name)
|
||||
exists := err == nil
|
||||
if exists && c.Mode == 1 {
|
||||
return &admin, nil
|
||||
}
|
||||
if err != nil && !errors.Is(err, util.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
replacements := params.getStringReplacements(false, true)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
data := replaceWithReplacer(c.TemplateAdmin, replacer)
|
||||
|
||||
var newAdmin dataprovider.Admin
|
||||
err = json.Unmarshal([]byte(data), &newAdmin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if newAdmin.Password == "" {
|
||||
newAdmin.Password = util.GenerateUniqueID()
|
||||
}
|
||||
if exists {
|
||||
eventManagerLog(logger.LevelDebug, "updating admin %q after IDP login", params.Name)
|
||||
err = dataprovider.UpdateAdmin(&newAdmin, dataprovider.ActionExecutorSystem, "", "")
|
||||
} else {
|
||||
eventManagerLog(logger.LevelDebug, "creating admin %q after IDP login", params.Name)
|
||||
err = dataprovider.AddAdmin(&newAdmin, dataprovider.ActionExecutorSystem, "", "")
|
||||
}
|
||||
return &newAdmin, err
|
||||
}
|
||||
|
||||
func executeUserCheckAction(c *dataprovider.EventActionIDPAccountCheck, params *EventParams) (*dataprovider.User, error) {
|
||||
user, err := dataprovider.UserExists(params.Name, "")
|
||||
exists := err == nil
|
||||
if exists && c.Mode == 1 {
|
||||
err = user.LoadAndApplyGroupSettings()
|
||||
return &user, err
|
||||
}
|
||||
if err != nil && !errors.Is(err, util.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
replacements := params.getStringReplacements(false, true)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
data := replaceWithReplacer(c.TemplateUser, replacer)
|
||||
|
||||
var newUser dataprovider.User
|
||||
err = json.Unmarshal([]byte(data), &newUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
eventManagerLog(logger.LevelDebug, "updating user %q after IDP login", params.Name)
|
||||
err = dataprovider.UpdateUser(&newUser, dataprovider.ActionExecutorSystem, "", "")
|
||||
} else {
|
||||
eventManagerLog(logger.LevelDebug, "creating user %q after IDP login", params.Name)
|
||||
err = dataprovider.AddUser(&newUser, dataprovider.ActionExecutorSystem, "", "")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u, err := dataprovider.GetUserWithGroupSettings(params.Name, "")
|
||||
return &u, err
|
||||
}
|
||||
|
||||
func executeRuleAction(action dataprovider.BaseEventAction, params *EventParams,
|
||||
conditions dataprovider.ConditionOptions,
|
||||
) error {
|
||||
@@ -2252,6 +2456,43 @@ func executeRuleAction(action dataprovider.BaseEventAction, params *EventParams,
|
||||
return err
|
||||
}
|
||||
|
||||
func executeIDPAccountCheckRule(rule dataprovider.EventRule, params EventParams) (*dataprovider.User,
|
||||
*dataprovider.Admin, error,
|
||||
) {
|
||||
for _, action := range rule.Actions {
|
||||
if action.Type == dataprovider.ActionTypeIDPAccountCheck {
|
||||
startTime := time.Now()
|
||||
var user *dataprovider.User
|
||||
var admin *dataprovider.Admin
|
||||
var err error
|
||||
var failedActions []string
|
||||
paramsCopy := params.getACopy()
|
||||
|
||||
switch params.Event {
|
||||
case IDPLoginAdmin:
|
||||
admin, err = executeAdminCheckAction(&action.BaseEventAction.Options.IDPConfig, paramsCopy)
|
||||
case IDPLoginUser:
|
||||
user, err = executeUserCheckAction(&action.BaseEventAction.Options.IDPConfig, paramsCopy)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported IDP login event: %q", params.Event)
|
||||
}
|
||||
if err != nil {
|
||||
paramsCopy.AddError(fmt.Errorf("unable to handle %q: %w", params.Event, err))
|
||||
eventManagerLog(logger.LevelError, "unable to handle IDP login event %q, err: %v", params.Event, err)
|
||||
failedActions = append(failedActions, action.Name)
|
||||
} else {
|
||||
eventManagerLog(logger.LevelDebug, "executed action %q for rule %q, elapsed %s",
|
||||
action.Name, rule.Name, time.Since(startTime))
|
||||
}
|
||||
// execute async actions if any, including failure actions
|
||||
go executeRuleAsyncActions(rule, paramsCopy, failedActions)
|
||||
return user, admin, err
|
||||
}
|
||||
}
|
||||
eventManagerLog(logger.LevelError, "no action executed for IDP login event %q, event rule: %q", params.Event, rule.Name)
|
||||
return nil, nil, errors.New("no action executed")
|
||||
}
|
||||
|
||||
func executeSyncRulesActions(rules []dataprovider.EventRule, params EventParams) error {
|
||||
var errRes error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user