Skip to content

Commit

Permalink
Merge pull request #20 from meirish/b-post-auth-redirect
Browse files Browse the repository at this point in the history
Save target url in SessionStorage for post-auth redirect; Add EmberSimpleAuth types
  • Loading branch information
jeffdaley committed Feb 3, 2023
2 parents a2b9435 + 35c5edb commit 5d0b607
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 37 deletions.
21 changes: 2 additions & 19 deletions web/app/controllers/authenticate.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
import Controller from "@ember/controller";
import { inject as service } from "@ember/service";
import { action } from "@ember/object";
import RouterService from "@ember/routing/router-service";
import Transition from "@ember/routing/transition";
import SessionService from "hermes/services/session";

export default class AuthenticateController extends Controller {
@service declare router: RouterService;
@service declare session: any;

previousTransition: Transition | null = null;
@service declare session: SessionService;

protected get currentYear(): number {
return new Date().getFullYear();
}

@action protected authenticate(): void {
this.session.authenticate("authenticator:torii", "google-oauth2-bearer");

// Capture the previousTransition locally if it exists
let _previousTransition = this.previousTransition;

if (_previousTransition) {
// Clear the previousTransition class property
this.previousTransition = null;

// Retry the initial transition
_previousTransition.retry();
} else {
this.router.transitionTo("authenticated.dashboard");
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion web/app/routes/authenticate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
import SessionService from "hermes/services/session";

export default class AuthenticateRoute extends Route {
@service declare session: any;
@service declare session: SessionService;

beforeModel() {
this.session.prohibitAuthentication("/");
Expand Down
32 changes: 18 additions & 14 deletions web/app/routes/authenticated.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
import ConfigService from "hermes/services/config";
import AuthenticateController from "hermes/controllers/authenticate";
import AuthenticatedUserService from "hermes/services/authenticated-user";
import Transition from "@ember/routing/transition";
import window from "ember-window-mock";
import SessionService from "hermes/services/session";

export default class AuthenticatedRoute extends Route {
@service declare session: any;
@service declare session: SessionService;
@service declare authenticatedUser: AuthenticatedUserService;
@service("config") declare configSvc: ConfigService;

async afterModel(): Promise<void> {
// Load user info
await this.authenticatedUser.loadInfo.perform();
}

async beforeModel(transition: Transition): Promise<void> {
// Check if the request requires authentication and if so, preserve the URL
async beforeModel(transition: any): Promise<void> {
// If the user isn't authenticated, transition to the auth screen
let requireAuthentication = this.session.requireAuthentication(
transition,
"authenticate"
);

if (!requireAuthentication && transition.to.name != "authenticated.index") {
let authenticateController = this.controllerFor(
"authenticate"
) as AuthenticateController;
let target = window.sessionStorage.getItem(
this.session.SESSION_STORAGE_KEY
);
if (
!target &&
!requireAuthentication &&
transition.to.name != "authenticated"
) {
// ember-simple-auth uses this value to set cookies when fastboot is enabled: https://github.com/mainmatter/ember-simple-auth/blob/a7e583cf4d04d6ebc96b198a8fa6dde7445abf0e/packages/ember-simple-auth/addon/-internals/routing.js#L12

// Set previous transition to preserve URL
authenticateController.previousTransition = transition;
window.sessionStorage.setItem(
this.session.SESSION_STORAGE_KEY,
transition.intent.url
);
}
}
}
5 changes: 3 additions & 2 deletions web/app/services/algolia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { assert } from "@ember/debug";
import ConfigService from "./config";
import { FacetOption, FacetRecord, FacetRecords } from "hermes/types/facets";
import FetchService from "./fetch";
import SessionService from "./session";

export const HITS_PER_PAGE = 12;
export const MAX_VALUES_PER_FACET = 100;
Expand All @@ -26,9 +27,9 @@ export type AlgoliaFacetsObject = NonNullable<SearchResponse["facets"]>;
export default class AlgoliaService extends Service {
@service("config") declare configSvc: ConfigService;
@service("fetch") declare fetchSvc: FetchService;
@service declare session: SessionService;
@service declare authenticatedUser: AuthenticatedUserService;
// TODO: use actual type.
@service session: any;


/**
* A shorthand getter for the authenticatedUser's email.
Expand Down
3 changes: 2 additions & 1 deletion web/app/services/authenticated-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Store from "@ember-data/store";
import { assert } from "@ember/debug";
import { task } from "ember-concurrency";
import FetchService from "hermes/services/fetch";
import SessionService from "./session";

export interface AuthenticatedUser {
email: string;
Expand All @@ -25,8 +26,8 @@ enum SubscriptionType {

export default class AuthenticatedUserService extends Service {
@service("fetch") declare fetchSvc: FetchService;
@service declare session: SessionService;
@service declare store: Store;
@service declare session: any;

@tracked subscriptions: Subscription[] | null = null;
@tracked private _info: AuthenticatedUser | null = null;
Expand Down
28 changes: 28 additions & 0 deletions web/app/services/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { inject as service } from "@ember/service";
import RouterService from "@ember/routing/router-service";
import EmberSimpleAuthSessionService from "ember-simple-auth/services/session";
import window from "ember-window-mock";

export default class SessionService extends EmberSimpleAuthSessionService {
@service declare router: RouterService;

readonly SESSION_STORAGE_KEY: string = "hermes.redirectTarget";

// ember-simple-auth only uses a cookie to track redirect target if you're using fastboot, otherwise it keeps track of the redirect target as a parameter on the session service. See the source here: https://github.com/mainmatter/ember-simple-auth/blob/a7e583cf4d04d6ebc96b198a8fa6dde7445abf0e/packages/ember-simple-auth/addon/-internals/routing.js#L33-L50
//
// Because we redirect as part of the authentication flow, the parameter storing the transition gets reset. Instead, we keep track of the redirectTarget in browser sessionStorage and override the handleAuthentication method as recommended by ember-simple-auth.

handleAuthentication(routeAfterAuthentication: string) {
let redirectTarget = window.sessionStorage.getItem(this.SESSION_STORAGE_KEY);
let transition;

if (redirectTarget) {
transition = this.router.transitionTo(redirectTarget);
} else {
transition = this.router.transitionTo(routeAfterAuthentication);
}
transition.followRedirects().then(() => {
window.sessionStorage.removeItem(this.SESSION_STORAGE_KEY);
});
}
}
25 changes: 25 additions & 0 deletions web/types/ember-simple-auth/services/session.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Reference: https://github.com/mainmatter/ember-simple-auth/blob/master/packages/ember-simple-auth/addon/services/session.js

import Service from "@ember/service";
import Evented from "@ember/object/evented";
import Transition from "@ember/routing/transition";

export interface Data {
authenticated: {
access_token: string;
};
}

declare module "ember-simple-auth/services/session" {
export default class EmberSimpleAuthSessionService extends Service.extend(Evented) {
data: Data;
setup: () => void;
authenticate(...args: any[]): RSVP.Promise;
invalidate(...args: any): RSVP.Promise;
requireAuthentication(
transition: Transition,
routeOrCallback: string | function
): RSVP.Promise;
prohibitAuthentication(routeOrCallback: string | function): RSVP.Promise;
}
}

0 comments on commit 5d0b607

Please sign in to comment.