Skip to content

Commit

Permalink
Implement new wasp/auth API
Browse files Browse the repository at this point in the history
  • Loading branch information
infomiho committed Jan 29, 2024
1 parent 86a4035 commit 716b714
Show file tree
Hide file tree
Showing 26 changed files with 87 additions and 78 deletions.
6 changes: 6 additions & 0 deletions waspc/data/Generator/templates/sdk/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export { defineUserSignupFields } from './providers/types.js';

// PUBLIC
export type { AuthUser } from '../server/_types'

// PUBLIC
export { getEmail, getUsername, getFirstProviderUserId, findUserIdentity } from './user.js'
8 changes: 4 additions & 4 deletions waspc/data/Generator/templates/sdk/auth/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Request as ExpressRequest } from "express";

import { type {= userEntityUpper =} } from "wasp/entities"
import { type SanitizedUser } from 'wasp/server/_types'
import { type AuthUser } from 'wasp/server/_types'

import { auth } from "./lucia.js";
import type { Session } from "lucia";
Expand All @@ -19,7 +19,7 @@ export async function createSession(authId: string): Promise<Session> {
}

export async function getSessionAndUserFromBearerToken(req: ExpressRequest): Promise<{
user: SanitizedUser | null,
user: AuthUser | null,
session: Session | null,
}> {
const authorizationHeader = req.headers["authorization"];
Expand All @@ -43,7 +43,7 @@ export async function getSessionAndUserFromBearerToken(req: ExpressRequest): Pro
}

export async function getSessionAndUserFromSessionId(sessionId: string): Promise<{
user: SanitizedUser | null,
user: AuthUser | null,
session: Session | null,
}> {
const { session, user: authEntity } = await auth.validateSession(sessionId);
Expand All @@ -61,7 +61,7 @@ export async function getSessionAndUserFromSessionId(sessionId: string): Promise
}
}

async function getUser(userId: {= userEntityUpper =}['id']): Promise<SanitizedUser> {
async function getUser(userId: {= userEntityUpper =}['id']): Promise<AuthUser> {
const user = await prisma.{= userEntityLower =}
.findUnique({
where: { id: userId },
Expand Down
2 changes: 1 addition & 1 deletion waspc/data/Generator/templates/sdk/auth/types.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// todo(filip): turn into a proper import/path
export type { SanitizedUser as User, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types/'
export type { AuthUser, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types/'
4 changes: 2 additions & 2 deletions waspc/data/Generator/templates/sdk/auth/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { deserialize as superjsonDeserialize } from 'superjson'
import { useQuery } from 'wasp/rpc'
import { api, handleApiError } from 'wasp/client/api'
import { HttpMethod } from 'wasp/types'
import type { User } from './types'
import type { AuthUser } from './types'
import { addMetadataToQuery } from 'wasp/rpc/queries'

export const getMe = createUserGetter()
Expand All @@ -15,7 +15,7 @@ export default function useAuth(queryFnArgs?: unknown, config?: any) {
function createUserGetter() {
const getMeRelativePath = 'auth/me'
const getMeRoute = { method: HttpMethod.Get, path: `/${getMeRelativePath}` }
async function getMe(): Promise<User | null> {
async function getMe(): Promise<AuthUser | null> {
try {
const response = await api.get(getMeRoute.path)

Expand Down
10 changes: 5 additions & 5 deletions waspc/data/Generator/templates/sdk/auth/user.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import type { User, ProviderName, DeserializedAuthIdentity } from './types'
import type { AuthUser, ProviderName, DeserializedAuthIdentity } from './types'

export function getEmail(user: User): string | null {
export function getEmail(user: AuthUser): string | null {
return findUserIdentity(user, "email")?.providerUserId ?? null;
}

export function getUsername(user: User): string | null {
export function getUsername(user: AuthUser): string | null {
return findUserIdentity(user, "username")?.providerUserId ?? null;
}

export function getFirstProviderUserId(user?: User): string | null {
export function getFirstProviderUserId(user?: AuthUser): string | null {
if (!user || !user.auth || !user.auth.identities || user.auth.identities.length === 0) {
return null;
}

return user.auth.identities[0].providerUserId ?? null;
}

export function findUserIdentity(user: User, providerName: ProviderName): DeserializedAuthIdentity | undefined {
export function findUserIdentity(user: AuthUser, providerName: ProviderName): DeserializedAuthIdentity | undefined {
return user.auth.identities.find(
(identity) => identity.providerName === providerName
);
Expand Down
9 changes: 2 additions & 7 deletions waspc/data/Generator/templates/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
"./rpc/queryClient": "./dist/rpc/queryClient.js",
{=! Used by users, documented. =}
"./types": "./dist/types/index.js",
{=! Used by user, documented. =}
"./auth": "./dist/auth/index.js",
{=! Used by users, documented. =}
"./auth/types": "./dist/auth/types.js",
{=! Used by users, documented. =}
"./auth/login": "./dist/auth/login.js",
{=! Used by users, documented. =}
Expand All @@ -50,8 +46,6 @@
{=! Used by users, documented. =}
"./auth/useAuth": "./dist/auth/useAuth.js",
{=! Used by users, documented. =}
"./auth/user": "./dist/auth/user.js",
{=! Used by users, documented. =}
"./auth/email": "./dist/auth/email/index.js",
{=! Used by our code, uncodumented (but accessible) for users. =}
"./auth/helpers/user": "./dist/auth/helpers/user.js",
Expand Down Expand Up @@ -150,7 +144,8 @@
"./server/api": "./dist/server/api/index.js",
{=! Public: { api } =}
{=! Private: [sdk] =}
"./client/api": "./dist/api/index.js"
"./client/api": "./dist/api/index.js",
"./auth": "./dist/auth/index.js"
},
{=!
TypeScript doesn't care about the redirects we define above in "exports" field; those
Expand Down
4 changes: 2 additions & 2 deletions waspc/data/Generator/templates/sdk/server/_types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ type Context<Entities extends _Entity[]> = Expand<{
}>

{=# isAuthEnabled =}
type ContextWithUser<Entities extends _Entity[]> = Expand<Context<Entities> & { user?: SanitizedUser }>
type ContextWithUser<Entities extends _Entity[]> = Expand<Context<Entities> & { user?: AuthUser }>

// TODO: This type must match the logic in auth/session.js (if we remove the
// password field from the object there, we must do the same here). Ideally,
Expand All @@ -97,7 +97,7 @@ export type DeserializedAuthIdentity = Expand<Omit<{= authIdentityEntityName =},
providerData: Omit<EmailProviderData, 'password'> | Omit<UsernameProviderData, 'password'> | OAuthProviderData
}>

export type SanitizedUser = {= userEntityName =} & {
export type AuthUser = {= userEntityName =} & {
{= authFieldOnUserEntityName =}: {= authEntityName =} & {
{= identitiesFieldOnAuthEntityName =}: DeserializedAuthIdentity[]
} | null
Expand Down
4 changes: 2 additions & 2 deletions waspc/data/Generator/templates/sdk/server/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { dirname } from 'path'
import { fileURLToPath } from 'url'

{=# isAuthEnabled =}
import { type SanitizedUser } from 'wasp/server/_types/index.js'
import { type AuthUser } from 'wasp/auth'
{=/ isAuthEnabled =}

type RequestWithExtraFields = Request & {
{=# isAuthEnabled =}
user?: SanitizedUser;
user?: AuthUser;
sessionId?: string;
{=/ isAuthEnabled =}
}
Expand Down
4 changes: 2 additions & 2 deletions waspc/data/Generator/templates/sdk/server/webSocket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { EventsMap, DefaultEventsMap } from '@socket.io/component-emitter'

import { prisma } from 'wasp/server'
{=# isAuthEnabled =}
import { type SanitizedUser } from 'wasp/server/_types/index.js'
import { type AuthUser } from 'wasp/auth'
{=/ isAuthEnabled =}

{=& userWebSocketFn.importStatement =}
Expand Down Expand Up @@ -33,7 +33,7 @@ export type WebSocketDefinition<

export interface WaspSocketData {
{=# isAuthEnabled =}
user?: SanitizedUser
user?: AuthUser
{=/ isAuthEnabled =}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { handleRejection } from 'wasp/server/utils'
import { MiddlewareConfigFn, globalMiddlewareConfigForExpress } from '../../middleware/index.js'
{=# isAuthEnabled =}
import auth from 'wasp/core/auth'
import { type SanitizedUser } from 'wasp/server/_types'
import { type AuthUser } from 'wasp/auth'
{=/ isAuthEnabled =}
{=# apiNamespaces =}
Expand Down Expand Up @@ -45,7 +45,7 @@ router.{= routeMethod =}(
{=/ usesAuth =}
handleRejection(
(
req: Parameters<typeof {= importIdentifier =}>[0]{=# usesAuth =} & { user: SanitizedUser }{=/ usesAuth =},
req: Parameters<typeof {= importIdentifier =}>[0]{=# usesAuth =} & { user: AuthUser }{=/ usesAuth =},
res: Parameters<typeof {= importIdentifier =}>[1],
) => {
const context = {
Expand Down
4 changes: 2 additions & 2 deletions waspc/data/Generator/templates/server/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { dirname } from 'path'
import { fileURLToPath } from 'url'

{=# isAuthEnabled =}
import { type SanitizedUser } from 'wasp/server/_types/index.js'
import { type AuthUser } from 'wasp/auth'
{=/ isAuthEnabled =}

type RequestWithExtraFields = Request & {
{=# isAuthEnabled =}
user?: SanitizedUser;
user?: AuthUser;
sessionId?: string;
{=/ isAuthEnabled =}
}
Expand Down
10 changes: 7 additions & 3 deletions waspc/examples/todo-typescript/.wasp/out/sdk/wasp/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,35 @@ import config from 'wasp/core/config'
import { storage } from 'wasp/core/storage'
import { apiEventsEmitter } from './events.js'

const api = axios.create({
// PUBLIC API
export const api = axios.create({
baseURL: config.apiUrl,
})

const WASP_APP_AUTH_SESSION_ID_NAME = 'sessionId'

let waspAppAuthSessionId = storage.get(WASP_APP_AUTH_SESSION_ID_NAME) as string | undefined

// PRIVATE API (sdk)
export function setSessionId(sessionId: string): void {
waspAppAuthSessionId = sessionId
storage.set(WASP_APP_AUTH_SESSION_ID_NAME, sessionId)
apiEventsEmitter.emit('sessionId.set')
}

// PRIVATE API (sdk)
export function getSessionId(): string | undefined {
return waspAppAuthSessionId
}

// PRIVATE API (sdk)
export function clearSessionId(): void {
waspAppAuthSessionId = undefined
storage.remove(WASP_APP_AUTH_SESSION_ID_NAME)
apiEventsEmitter.emit('sessionId.clear')
}

// PRIVATE API (sdk)
export function removeLocalUserData(): void {
waspAppAuthSessionId = undefined
storage.clear()
Expand Down Expand Up @@ -66,6 +71,7 @@ window.addEventListener('storage', (event) => {
}
})

// PRIVATE API (sdk)
/**
* Takes an error returned by the app's API (as returned by axios), and transforms into a more
* standard format to be further used by the client. It is also assumed that given API
Expand Down Expand Up @@ -100,5 +106,3 @@ class WaspHttpError extends Error {
this.data = data
}
}

export default api
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setSessionId } from 'wasp/api'
import { setSessionId } from 'wasp/client/api'
import { invalidateAndRemoveQueries } from 'wasp/operations/resources'

export async function initSession(sessionId: string): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import api, { removeLocalUserData } from 'wasp/api'
import { api, removeLocalUserData } from 'wasp/client/api'
import { invalidateAndRemoveQueries } from 'wasp/operations/resources'

export default async function logout(): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// todo(filip): turn into a proper import/path
export type { SanitizedUser as User, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types/'
export type { AuthUser, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types/'
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { deserialize as superjsonDeserialize } from 'superjson'
import { useQuery } from 'wasp/rpc'
import api, { handleApiError } from 'wasp/api'
import { api, handleApiError } from 'wasp/client/api'
import { HttpMethod } from 'wasp/types'
import type { User } from './types'
import type { AuthUser } from './types'
import { addMetadataToQuery } from 'wasp/rpc/queries'

export const getMe = createUserGetter()
Expand All @@ -14,7 +14,7 @@ export default function useAuth(queryFnArgs?: unknown, config?: any) {
function createUserGetter() {
const getMeRelativePath = 'auth/me'
const getMeRoute = { method: HttpMethod.Get, path: `/${getMeRelativePath}` }
async function getMe(): Promise<User | null> {
async function getMe(): Promise<AuthUser | null> {
try {
const response = await api.get(getMeRoute.path)

Expand Down
10 changes: 5 additions & 5 deletions waspc/examples/todo-typescript/.wasp/out/sdk/wasp/auth/user.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import type { User, ProviderName, DeserializedAuthIdentity } from './types'
import type { AuthUser, ProviderName, DeserializedAuthIdentity } from './types'

export function getEmail(user: User): string | null {
export function getEmail(user: AuthUser): string | null {
return findUserIdentity(user, "email")?.providerUserId ?? null;
}

export function getUsername(user: User): string | null {
export function getUsername(user: AuthUser): string | null {
return findUserIdentity(user, "username")?.providerUserId ?? null;
}

export function getFirstProviderUserId(user?: User): string | null {
export function getFirstProviderUserId(user?: AuthUser): string | null {
if (!user || !user.auth || !user.auth.identities || user.auth.identities.length === 0) {
return null;
}

return user.auth.identities[0].providerUserId ?? null;
}

export function findUserIdentity(user: User, providerName: ProviderName): DeserializedAuthIdentity | undefined {
export function findUserIdentity(user: AuthUser, providerName: ProviderName): DeserializedAuthIdentity | undefined {
return user.auth.identities.find(
(identity) => identity.providerName === providerName
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { hashPassword } from './password.js'
import { verify } from './jwt.js'
import AuthError from 'wasp/core/AuthError'
import HttpError from 'wasp/core/HttpError'
import prisma from 'wasp/server/dbClient'
import { prisma } from 'wasp/server'
import { sleep } from 'wasp/server/utils'
import {
type User,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import api, { handleApiError } from 'wasp/api'
import { api, handleApiError } from 'wasp/client/api'
import { HttpMethod } from 'wasp/types'
import {
serialize as superjsonSerialize,
Expand Down
Loading

0 comments on commit 716b714

Please sign in to comment.