Skip to content

Commit 173c32e

Browse files
committed
session: migrate sudo tracking to a task
1 parent e9d51bd commit 173c32e

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

app/services/session.js

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Service, { inject as service } from '@ember/service';
22
import { tracked } from '@glimmer/tracking';
33

4-
import { dropTask, race, rawTimeout, task, waitForEvent } from 'ember-concurrency';
4+
import { dropTask, race, rawTimeout, restartableTask, task, waitForEvent } from 'ember-concurrency';
55
import window from 'ember-window-mock';
66
import { alias } from 'macro-decorators';
77

@@ -45,7 +45,7 @@ export default class SessionService extends Service {
4545
}
4646

4747
get isSudoEnabled() {
48-
return this.currentUser?.is_admin === true && this.sudoEnabledUntil !== null && this.sudoEnabledUntil >= Date.now();
48+
return this.currentUser?.is_admin === true && this.sudoTask.isRunning;
4949
}
5050

5151
/**
@@ -58,14 +58,12 @@ export default class SessionService extends Service {
5858
* immediately.
5959
*/
6060
setSudo(duration_ms) {
61-
if (this.currentUser?.is_admin) {
61+
if (this.isAdmin) {
6262
if (duration_ms) {
63-
const expiry = Date.now() + duration_ms;
64-
localStorage.setItem('sudo', expiry);
65-
this.sudoEnabledUntil = expiry;
63+
// eslint-disable-next-line ember-concurrency/no-perform-without-catch
64+
this.sudoTask.perform(Date.now() + duration_ms);
6665
} else {
67-
localStorage.removeItem('sudo');
68-
this.sudoEnabledUntil = null;
66+
this.sudoTask.cancelAll();
6967
}
7068
}
7169
}
@@ -204,7 +202,10 @@ export default class SessionService extends Service {
204202
const expiry = localStorage.getItem('sudo');
205203
if (expiry !== null) {
206204
try {
207-
this.sudoEnabledUntil = +expiry;
205+
// Trigger sudoTask, but without waiting for it to complete.
206+
//
207+
// eslint-disable-next-line ember-concurrency/no-perform-without-catch
208+
this.sudoTask.perform(+expiry);
208209
} catch {
209210
// It doesn't really matter if this fails; any invalid value will just
210211
// be treated as the user not being in sudo mode.
@@ -214,4 +215,30 @@ export default class SessionService extends Service {
214215

215216
return { currentUser, ownedCrates };
216217
});
218+
219+
sudoTask = restartableTask(async until => {
220+
try {
221+
const now = Date.now();
222+
223+
if (until > now) {
224+
// Since this task will replace any running task, we should update local
225+
// storage.
226+
localStorage.setItem('sudo', until.toString());
227+
228+
// We'll also surface the expiry as a property on the session service,
229+
// since that can be tracked and updated by other components.
230+
this.sudoEnabledUntil = until;
231+
232+
// Now we sleep until sudo mode has expired.
233+
await rawTimeout(until - now);
234+
}
235+
} finally {
236+
// Clear the local storage, since we're no longer in sudo mode, regardless
237+
// of whether the await finished or the task was cancelled.
238+
localStorage.removeItem('sudo');
239+
240+
// Again, update the session service property.
241+
this.sudoEnabledUntil = null;
242+
}
243+
});
217244
}

0 commit comments

Comments
 (0)