Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import InitialOAuthTokenService from "../../src/features/auth/domain/oAuthToken/InitialOAuthTokenService"
import CredentialsTransferrer from "../../src/features/auth/domain/credentialsTransfer/CredentialsTransferrer"
import OAuthToken from "../../src/features/auth/domain/oAuthToken/OAuthToken"

test("It fetches refresh token for specified user", async () => {
let fetchedUserId: string | undefined
const sut = new InitialOAuthTokenService({
const sut = new CredentialsTransferrer({
refreshTokenReader: {
async getRefreshToken(userId) {
fetchedUserId = userId
Expand All @@ -23,13 +23,13 @@ test("It fetches refresh token for specified user", async () => {
async delete() {}
}
})
await sut.fetchInitialAuthTokenForUser("123")
await sut.transferCredentials("123")
expect(fetchedUserId).toBe("123")
})

test("It refreshes the fetched refresh token", async () => {
let refreshedRefreshToken: string | undefined
const sut = new InitialOAuthTokenService({
const sut = new CredentialsTransferrer({
refreshTokenReader: {
async getRefreshToken() {
return "helloworld"
Expand All @@ -49,14 +49,14 @@ test("It refreshes the fetched refresh token", async () => {
async delete() {}
}
})
await sut.fetchInitialAuthTokenForUser("123")
await sut.transferCredentials("123")
expect(refreshedRefreshToken).toBe("helloworld")
})

test("It stores the refreshed auth token for the correct user ID", async () => {
test("It stores the refreshed auth token for the user", async () => {
let storedAuthToken: OAuthToken | undefined
let storedUserId: string | undefined
const sut = new InitialOAuthTokenService({
const sut = new CredentialsTransferrer({
refreshTokenReader: {
async getRefreshToken() {
return "helloworld"
Expand All @@ -78,7 +78,7 @@ test("It stores the refreshed auth token for the correct user ID", async () => {
async delete() {}
}
})
await sut.fetchInitialAuthTokenForUser("123")
await sut.transferCredentials("123")
expect(storedAuthToken?.accessToken).toBe("foo")
expect(storedAuthToken?.refreshToken).toBe("bar")
expect(storedUserId).toBe("123")
Expand Down
12 changes: 12 additions & 0 deletions __test__/auth/CredentialsTransferringLogInHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import CredentialsTransferringLogInHandler from "../../src/features/auth/domain/logIn/CredentialsTransferringLogInHandler"

test("It transfers credentials", async () => {
let didTransferCredentials = false
const sut = new CredentialsTransferringLogInHandler({
async transferCredentials() {
didTransferCredentials = true
}
})
await sut.handleLogIn("1234")
expect(didTransferCredentials).toBeTruthy()
})
4 changes: 2 additions & 2 deletions src/app/api/auth/[auth0]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import {
NextAppRouterHandler,
AppRouterOnError
} from "@auth0/nextjs-auth0"
import { initialOAuthTokenService, logOutHandler } from "@/composition"
import { logInHandler, logOutHandler } from "@/composition"

const { SHAPE_DOCS_BASE_URL } = process.env

const afterCallback: AfterCallbackAppRoute = async (_req, session) => {
await initialOAuthTokenService.fetchInitialAuthTokenForUser(session.user.sub)
await logInHandler.handleLogIn(session.user.sub)
return session
}

Expand Down
31 changes: 17 additions & 14 deletions src/composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import Auth0RefreshTokenReader from "@/features/auth/data/Auth0RefreshTokenReade
import Auth0Session from "@/common/session/Auth0Session"
import CachingProjectDataSource from "@/features/projects/domain/CachingProjectDataSource"
import CompositeLogOutHandler from "@/features/auth/domain/logOut/CompositeLogOutHandler"
import CredentialsTransferrer from "@/features/auth/domain/credentialsTransfer/CredentialsTransferrer"
import CredentialsTransferringLogInHandler from "@/features/auth/domain/logIn/CredentialsTransferringLogInHandler"
import ErrorIgnoringLogOutHandler from "@/features/auth/domain/logOut/ErrorIgnoringLogOutHandler"
import GitHubClient from "@/common/github/GitHubClient"
import GitHubOAuthTokenRefresher from "@/features/auth/data/GitHubOAuthTokenRefresher"
import GitHubOrganizationSessionValidator from "@/common/session/GitHubOrganizationSessionValidator"
import GitHubProjectDataSource from "@/features/projects/data/GitHubProjectDataSource"
import InitialOAuthTokenService from "@/features/auth/domain/oAuthToken/InitialOAuthTokenService"
import KeyValueUserDataRepository from "@/common/userData/KeyValueUserDataRepository"
import LockingAccessTokenService from "@/features/auth/domain/accessToken/LockingAccessTokenService"
import OnlyStaleRefreshingAccessTokenService from "@/features/auth/domain/accessToken/OnlyStaleRefreshingAccessTokenService"
Expand Down Expand Up @@ -99,19 +100,21 @@ export const projectDataSource = new CachingProjectDataSource(
projectRepository
)

export const initialOAuthTokenService = new InitialOAuthTokenService({
refreshTokenReader: new Auth0RefreshTokenReader({
domain: AUTH0_MANAGEMENT_DOMAIN,
clientId: AUTH0_MANAGEMENT_CLIENT_ID,
clientSecret: AUTH0_MANAGEMENT_CLIENT_SECRET,
connection: "github"
}),
oAuthTokenRefresher: new GitHubOAuthTokenRefresher({
clientId: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET
}),
oAuthTokenRepository: oAuthTokenRepository
})
export const logInHandler = new CredentialsTransferringLogInHandler(
new CredentialsTransferrer({
refreshTokenReader: new Auth0RefreshTokenReader({
domain: AUTH0_MANAGEMENT_DOMAIN,
clientId: AUTH0_MANAGEMENT_CLIENT_ID,
clientSecret: AUTH0_MANAGEMENT_CLIENT_SECRET,
connection: "github"
}),
oAuthTokenRefresher: new GitHubOAuthTokenRefresher({
clientId: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET
}),
oAuthTokenRepository: oAuthTokenRepository
})
)

export const logOutHandler = new ErrorIgnoringLogOutHandler(
new CompositeLogOutHandler([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import IOAuthTokenRefresher from "../oAuthToken/IOAuthTokenRefresher"
import IOAuthTokenRepository from "../oAuthToken/IOAuthTokenRepository"
import ICredentialsTransferrer from "./ICredentialsTransferrer"

export interface IRefreshTokenReader {
getRefreshToken(userId: string): Promise<string>
}

type CredentialsTransferrerConfig = {
readonly refreshTokenReader: IRefreshTokenReader
readonly oAuthTokenRefresher: IOAuthTokenRefresher
readonly oAuthTokenRepository: IOAuthTokenRepository
}

export default class CredentialsTransferrer implements ICredentialsTransferrer {
private readonly refreshTokenReader: IRefreshTokenReader
private readonly oAuthTokenRefresher: IOAuthTokenRefresher
private readonly oAuthTokenRepository: IOAuthTokenRepository

constructor(config: CredentialsTransferrerConfig) {
this.refreshTokenReader = config.refreshTokenReader
this.oAuthTokenRefresher = config.oAuthTokenRefresher
this.oAuthTokenRepository = config.oAuthTokenRepository
}

async transferCredentials(userId: string): Promise<void> {
const refreshToken = await this.refreshTokenReader.getRefreshToken(userId)
const authToken = await this.oAuthTokenRefresher.refreshOAuthToken(refreshToken)
await this.oAuthTokenRepository.set(userId, authToken)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default interface ICredentialsTransferrer {
transferCredentials(userId: string): Promise<void>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import ICredentialsTransferrer from "../credentialsTransfer/ICredentialsTransferrer"
import ILogInHandler from "./ILogInHandler"

export interface IRefreshTokenReader {
getRefreshToken(userId: string): Promise<string>
}

export default class CredentialsTransferringLogInHandler implements ILogInHandler {
private readonly credentialsTransferrer: ICredentialsTransferrer

constructor(credentialsTransferrer: ICredentialsTransferrer) {
this.credentialsTransferrer = credentialsTransferrer
}

async handleLogIn(userId: string): Promise<void> {
await this.credentialsTransferrer.transferCredentials(userId)
}
}
3 changes: 3 additions & 0 deletions src/features/auth/domain/logIn/ILogInHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default interface ILogInHandler {
handleLogIn(userId: string): Promise<void>
}
26 changes: 0 additions & 26 deletions src/features/auth/domain/oAuthToken/InitialOAuthTokenService.ts

This file was deleted.