ensure migration dialog doesn't open automatically if it was opened manually (#13551)

for #13505
This commit is contained in:
Roberto Dip 2023-08-30 19:54:42 -03:00 committed by GitHub
parent 34474b2e1d
commit 8f8a3758f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 19 deletions

View File

@ -0,0 +1 @@
* Ensure migration dialog is not opened automatically if it was opened manually in the last 15 minutes

View File

@ -154,12 +154,15 @@ func (b *baseDialog) render(flags ...string) (chan swiftDialogExitCode, chan err
return exitCodeCh, errCh
}
// NewMDMMigrator creates a new swiftDialogMDMMigrator with the right internal state.
func NewMDMMigrator(path string, frequency time.Duration, handler MDMMigratorHandler) MDMMigrator {
return &swiftDialogMDMMigrator{
handler: handler,
baseDialog: newBaseDialog(path),
frequency: frequency,
unenrollmentRetryInterval: defaultUnenrollmentRetryInterval,
// set a buffer size of 1 to allow one Show without blocking
showCh: make(chan struct{}, 1),
}
}
@ -173,11 +176,9 @@ type swiftDialogMDMMigrator struct {
// ensures only one dialog is open at a time, protects access to
// lastShown
showMu sync.Mutex
lastShown time.Time
// ensures only one dialog is open at a given interval
intervalMu sync.Mutex
lastShownMu sync.RWMutex
showCh chan struct{}
// testEnrollmentCheckFn is used in tests to mock the call to verify
// the enrollment status of the host
@ -373,28 +374,43 @@ func (m *swiftDialogMDMMigrator) renderMigration() error {
return nil
}
// Show displays the dialog every time is called, as long as there isn't a
// dialog already open.
func (m *swiftDialogMDMMigrator) Show() error {
if m.showMu.TryLock() {
defer m.showMu.Unlock()
select {
case m.showCh <- struct{}{}:
defer func() { <-m.showCh }()
default:
log.Info().Msg("there's a migration dialog already open, refusing to launch")
return nil
}
if err := m.renderMigration(); err != nil {
return fmt.Errorf("show: %w", err)
}
}
m.lastShownMu.Lock()
m.lastShown = time.Now()
m.lastShownMu.Unlock()
return nil
}
// ShowInterval acts as a rate limiter for Show, it only calls the function IIF
// m.frequency has passed since the last time the dialog was successfully
// shown.
func (m *swiftDialogMDMMigrator) ShowInterval() error {
if m.intervalMu.TryLock() {
defer m.intervalMu.Unlock()
if time.Since(m.lastShown) > m.frequency {
m.lastShownMu.RLock()
lastShown := m.lastShown
m.lastShownMu.RUnlock()
if time.Since(lastShown) <= m.frequency {
log.Info().Msg("dialog was automatically launched too recently, skipping")
return nil
}
if err := m.Show(); err != nil {
return fmt.Errorf("show interval: %w", err)
}
m.lastShown = time.Now()
}
}
return nil
}