Merged in feat/basic-user (pull request #3135)
feat(SW-3610): Get basic user from api * feat(SW-3610): Get basic user from api * . * Optional profileid Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -3,6 +3,7 @@ import { headers } from "next/headers"
|
|||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
import { createContext } from "@scandic-hotels/trpc/context"
|
import { createContext } from "@scandic-hotels/trpc/context"
|
||||||
import { getEuroBonusProfileData } from "@scandic-hotels/trpc/routers/partners/sas/getEuroBonusProfile"
|
import { getEuroBonusProfileData } from "@scandic-hotels/trpc/routers/partners/sas/getEuroBonusProfile"
|
||||||
|
import { getBasicUser } from "@scandic-hotels/trpc/routers/user/utils/getBasicUser"
|
||||||
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils/getVerifiedUser"
|
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils/getVerifiedUser"
|
||||||
import {
|
import {
|
||||||
appServerClient,
|
appServerClient,
|
||||||
@@ -57,6 +58,19 @@ export async function createAppContext() {
|
|||||||
includeExtendedPartnerData: input?.withExtendedPartnerData,
|
includeExtendedPartnerData: input?.withExtendedPartnerData,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return user ?? null
|
||||||
|
},
|
||||||
|
getScandicBasicUser: async () => {
|
||||||
|
const session = await getSocialSession()
|
||||||
|
if (!session) return null
|
||||||
|
|
||||||
|
const user = await getBasicUser({
|
||||||
|
token: {
|
||||||
|
expires_at: dt(session.expires_at).unix() * 1000,
|
||||||
|
access_token: session.access_token,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return user ?? null
|
return user ?? null
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Lang } from "@scandic-hotels/common/constants/language"
|
|||||||
import { login } from "@scandic-hotels/common/constants/routes/handleAuth"
|
import { login } from "@scandic-hotels/common/constants/routes/handleAuth"
|
||||||
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createContext } from "@scandic-hotels/trpc/context"
|
import { createContext } from "@scandic-hotels/trpc/context"
|
||||||
|
import { getBasicUser } from "@scandic-hotels/trpc/routers/user/utils/getBasicUser"
|
||||||
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils/getVerifiedUser"
|
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils/getVerifiedUser"
|
||||||
import {
|
import {
|
||||||
appServerClient,
|
appServerClient,
|
||||||
@@ -85,6 +86,19 @@ export async function createAppContext() {
|
|||||||
includeExtendedPartnerData: input?.withExtendedPartnerData,
|
includeExtendedPartnerData: input?.withExtendedPartnerData,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return user ?? null
|
||||||
|
},
|
||||||
|
getScandicBasicUser: async () => {
|
||||||
|
const session = await getUserSession()
|
||||||
|
if (!session) return null
|
||||||
|
|
||||||
|
const user = await getBasicUser({
|
||||||
|
token: {
|
||||||
|
expires_at: session.token.expires_at ?? 0,
|
||||||
|
access_token: session.token.access_token,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return user ?? null
|
return user ?? null
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ export namespace endpoints {
|
|||||||
*/
|
*/
|
||||||
export namespace Profile {
|
export namespace Profile {
|
||||||
export const profile = `${base.path.profile}/${version}/${base.enitity.Profile}`
|
export const profile = `${base.path.profile}/${version}/${base.enitity.Profile}`
|
||||||
|
export const basicProfile = `${profile}/BasicInfo`
|
||||||
export const promoCampaign = `${profile}/Promotion`
|
export const promoCampaign = `${profile}/Promotion`
|
||||||
|
|
||||||
export function teamMemberCard(employeeId: string) {
|
export function teamMemberCard(employeeId: string) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Lang } from "@scandic-hotels/common/constants/language"
|
|||||||
import type { User } from "next-auth"
|
import type { User } from "next-auth"
|
||||||
import type { JWT } from "next-auth/jwt"
|
import type { JWT } from "next-auth/jwt"
|
||||||
|
|
||||||
|
import type { getBasicUser } from "./routers/user/utils/getBasicUser"
|
||||||
import type { getVerifiedUser } from "./routers/user/utils/getVerifiedUser"
|
import type { getVerifiedUser } from "./routers/user/utils/getVerifiedUser"
|
||||||
|
|
||||||
type Session = {
|
type Session = {
|
||||||
@@ -12,6 +13,7 @@ type Session = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ScandicUser = Awaited<ReturnType<typeof getVerifiedUser>>
|
type ScandicUser = Awaited<ReturnType<typeof getVerifiedUser>>
|
||||||
|
type ScandicBasicUser = Awaited<ReturnType<typeof getBasicUser>>
|
||||||
type CreateContextOptions = {
|
type CreateContextOptions = {
|
||||||
auth: () => Promise<Session | null>
|
auth: () => Promise<Session | null>
|
||||||
lang: Lang
|
lang: Lang
|
||||||
@@ -26,6 +28,7 @@ type CreateContextOptions = {
|
|||||||
getScandicUser: (input?: {
|
getScandicUser: (input?: {
|
||||||
withExtendedPartnerData: boolean
|
withExtendedPartnerData: boolean
|
||||||
}) => Promise<ScandicUser | null>
|
}) => Promise<ScandicUser | null>
|
||||||
|
getScandicBasicUser: () => Promise<ScandicBasicUser | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createContext(opts: CreateContextOptions) {
|
export function createContext(opts: CreateContextOptions) {
|
||||||
@@ -41,6 +44,7 @@ export function createContext(opts: CreateContextOptions) {
|
|||||||
getScandicUserToken: opts.getScandicUserToken,
|
getScandicUserToken: opts.getScandicUserToken,
|
||||||
getUserPointsBalance: opts.getUserPointsBalance,
|
getUserPointsBalance: opts.getUserPointsBalance,
|
||||||
getScandicUser: opts.getScandicUser,
|
getScandicUser: opts.getScandicUser,
|
||||||
|
getScandicBasicUser: opts.getScandicBasicUser,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
|||||||
import * as api from "../../../api"
|
import * as api from "../../../api"
|
||||||
import { protectedProcedure } from "../../../procedures"
|
import { protectedProcedure } from "../../../procedures"
|
||||||
import { getUserSchema } from "../../user/output"
|
import { getUserSchema } from "../../user/output"
|
||||||
import { getVerifiedUser } from "../../user/utils/getVerifiedUser"
|
import { getBasicUser } from "../../user/utils/getBasicUser"
|
||||||
|
|
||||||
import type { FriendsTier } from "../../../types/user"
|
import type { FriendsTier } from "../../../types/user"
|
||||||
|
|
||||||
@@ -33,12 +33,12 @@ export const performLevelUpgrade = protectedProcedure
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [profile, error] = await safeTry(
|
const [profile, error] = await safeTry(
|
||||||
getVerifiedUser({ token: ctx.session.token })
|
getBasicUser({ token: ctx.session.token })
|
||||||
)
|
)
|
||||||
if (!profile?.membership || error) {
|
if (!profile || error) {
|
||||||
return { tierMatchState: "error" }
|
return { tierMatchState: "error" }
|
||||||
}
|
}
|
||||||
const currentLevel = profile.membership.membershipLevel
|
const currentLevel = profile.tier
|
||||||
|
|
||||||
sasLogger.debug("tier match started")
|
sasLogger.debug("tier match started")
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,30 @@ export const getUserSchema = z
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const getBasicUserSchema = z.object({
|
||||||
|
dateOfBirth: z.string().optional().default("1900-01-01"),
|
||||||
|
firstName: z.string(),
|
||||||
|
language: z
|
||||||
|
.string()
|
||||||
|
.transform((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
||||||
|
.optional(),
|
||||||
|
lastName: z.string(),
|
||||||
|
phoneNumber: z.string().optional(),
|
||||||
|
profileId: z.string().optional(),
|
||||||
|
membershipNumber: z.string(),
|
||||||
|
tier: scandicFriendsTier,
|
||||||
|
address: z
|
||||||
|
.object({
|
||||||
|
city: z.string().optional(),
|
||||||
|
country: z.string().optional(),
|
||||||
|
countryCode: z.nativeEnum(countriesMap).optional(),
|
||||||
|
streetAddress: z.string().optional(),
|
||||||
|
zipCode: z.string().optional(),
|
||||||
|
})
|
||||||
|
.optional()
|
||||||
|
.nullable(),
|
||||||
|
})
|
||||||
|
|
||||||
export const creditCardSchema = z
|
export const creditCardSchema = z
|
||||||
.object({
|
.object({
|
||||||
attribute: z.object({
|
attribute: z.object({
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const userQueryRouter = router({
|
|||||||
if (!isValidSession(ctx.session)) {
|
if (!isValidSession(ctx.session)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const user = await ctx.getScandicUser()
|
const user = await ctx.getScandicBasicUser()
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import { createCounter } from "@scandic-hotels/common/telemetry"
|
|||||||
import { safeProtectedProcedure } from "../../../procedures"
|
import { safeProtectedProcedure } from "../../../procedures"
|
||||||
import { isValidSession } from "../../../utils/session"
|
import { isValidSession } from "../../../utils/session"
|
||||||
import { getEuroBonusProfileData } from "../../partners/sas/getEuroBonusProfile"
|
import { getEuroBonusProfileData } from "../../partners/sas/getEuroBonusProfile"
|
||||||
import { getFriendsMembership } from "../helpers"
|
import { getBasicUser } from "../utils/getBasicUser"
|
||||||
import { getVerifiedUser } from "../utils/getVerifiedUser"
|
|
||||||
|
|
||||||
import type { LoginType } from "@scandic-hotels/common/constants/loginType"
|
import type { LoginType } from "@scandic-hotels/common/constants/loginType"
|
||||||
import type { Session } from "next-auth"
|
import type { Session } from "next-auth"
|
||||||
@@ -48,9 +47,9 @@ async function getScandicFriendsUserTrackingData(session: Session | null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const verifiedUserData = await getVerifiedUser({ token: session.token })
|
const verifiedUserData = await getBasicUser({ token: session.token })
|
||||||
|
|
||||||
if (!verifiedUserData || !verifiedUserData.loyalty) {
|
if (!verifiedUserData) {
|
||||||
metricsUserTrackingInfo.success({
|
metricsUserTrackingInfo.success({
|
||||||
reason: "invalid user data",
|
reason: "invalid user data",
|
||||||
data: notLoggedInUserTrackingData,
|
data: notLoggedInUserTrackingData,
|
||||||
@@ -58,14 +57,12 @@ async function getScandicFriendsUserTrackingData(session: Session | null) {
|
|||||||
return notLoggedInUserTrackingData
|
return notLoggedInUserTrackingData
|
||||||
}
|
}
|
||||||
|
|
||||||
const membership = getFriendsMembership(verifiedUserData.loyalty)
|
|
||||||
|
|
||||||
const loggedInUserTrackingData: TrackingUserData = {
|
const loggedInUserTrackingData: TrackingUserData = {
|
||||||
loginStatus: "logged in",
|
loginStatus: "logged in",
|
||||||
loginType: session.token.loginType as LoginType,
|
loginType: session.token.loginType as LoginType,
|
||||||
memberId: verifiedUserData.profileId,
|
memberId: verifiedUserData.profileId,
|
||||||
membershipNumber: membership?.membershipNumber,
|
membershipNumber: verifiedUserData.membershipNumber,
|
||||||
memberLevel: membership?.membershipLevel,
|
memberLevel: verifiedUserData?.tier,
|
||||||
loginAction: "login success",
|
loginAction: "login success",
|
||||||
memberType,
|
memberType,
|
||||||
}
|
}
|
||||||
@@ -126,19 +123,17 @@ async function getSasEurobonusUserTrackingData(
|
|||||||
async function getScandicFriendsDataHelper(scandicUserToken: string | null) {
|
async function getScandicFriendsDataHelper(scandicUserToken: string | null) {
|
||||||
if (!scandicUserToken) return null
|
if (!scandicUserToken) return null
|
||||||
|
|
||||||
const verifiedUserData = await getVerifiedUser({
|
const verifiedUserData = await getBasicUser({
|
||||||
token: { access_token: scandicUserToken },
|
token: { access_token: scandicUserToken },
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!verifiedUserData || !verifiedUserData.loyalty) {
|
if (!verifiedUserData) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const membership = getFriendsMembership(verifiedUserData.loyalty)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
memberId: verifiedUserData.profileId,
|
memberId: verifiedUserData.profileId,
|
||||||
membershipNumber: membership?.membershipNumber,
|
membershipNumber: verifiedUserData.membershipNumber,
|
||||||
memberLevel: membership?.membershipLevel,
|
memberLevel: verifiedUserData.tier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { cache } from "../../DUPLICATED/cache"
|
|||||||
import { creditCardsSchema } from "../../routers/user/output"
|
import { creditCardsSchema } from "../../routers/user/output"
|
||||||
import { toApiLang } from "../../utils"
|
import { toApiLang } from "../../utils"
|
||||||
import { encrypt } from "../../utils/encryption"
|
import { encrypt } from "../../utils/encryption"
|
||||||
import { getVerifiedUser } from "./utils/getVerifiedUser"
|
import { getBasicUser } from "./utils/getBasicUser"
|
||||||
import { type FriendTransaction, getStaysSchema, type Stay } from "./output"
|
import { type FriendTransaction, getStaysSchema, type Stay } from "./output"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
@@ -190,7 +190,7 @@ export async function updateStaysBookingUrl(
|
|||||||
lang: Lang
|
lang: Lang
|
||||||
) {
|
) {
|
||||||
const [user, error] = await safeTry(
|
const [user, error] = await safeTry(
|
||||||
getVerifiedUser({
|
getBasicUser({
|
||||||
token: session.token,
|
token: session.token,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
48
packages/trpc/lib/routers/user/utils/getBasicUser.ts
Normal file
48
packages/trpc/lib/routers/user/utils/getBasicUser.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
|
|
||||||
|
import * as api from "../../../api"
|
||||||
|
import { cache } from "../../../DUPLICATED/cache"
|
||||||
|
import { serverErrorByStatus, sessionExpiredError } from "../../../errors"
|
||||||
|
import { getBasicUserSchema } from "../output"
|
||||||
|
|
||||||
|
export const getBasicUser = cache(
|
||||||
|
async ({
|
||||||
|
token,
|
||||||
|
}: {
|
||||||
|
token: { expires_at?: number; access_token: string }
|
||||||
|
}) => {
|
||||||
|
const getBasicUserCounter = createCounter("user", "getBasicUser")
|
||||||
|
const metricsGetBasicUser = getBasicUserCounter.init()
|
||||||
|
|
||||||
|
metricsGetBasicUser.start()
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
if (token.expires_at && token.expires_at < now) {
|
||||||
|
metricsGetBasicUser.dataError(`Token expired`)
|
||||||
|
throw sessionExpiredError()
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiResponse = await api.get(api.endpoints.v2.Profile.basicProfile, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token.access_token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!apiResponse.ok) {
|
||||||
|
await metricsGetBasicUser.httpError(apiResponse)
|
||||||
|
|
||||||
|
throw serverErrorByStatus(apiResponse.status, apiResponse)
|
||||||
|
}
|
||||||
|
const apiJson = await apiResponse.json()
|
||||||
|
|
||||||
|
const verifiedData = getBasicUserSchema.safeParse(apiJson)
|
||||||
|
if (!verifiedData.success) {
|
||||||
|
metricsGetBasicUser.validationError(verifiedData.error)
|
||||||
|
throw verifiedData.error
|
||||||
|
}
|
||||||
|
|
||||||
|
metricsGetBasicUser.success()
|
||||||
|
|
||||||
|
return verifiedData.data
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -5,7 +5,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
|||||||
|
|
||||||
import { env } from "../../../../env/server"
|
import { env } from "../../../../env/server"
|
||||||
import { encrypt } from "../../../utils/encryption"
|
import { encrypt } from "../../../utils/encryption"
|
||||||
import { getVerifiedUser } from "./getVerifiedUser"
|
import { getBasicUser } from "./getBasicUser"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import type { Session } from "next-auth"
|
import type { Session } from "next-auth"
|
||||||
@@ -30,7 +30,7 @@ export async function updateStaysBookingUrl(
|
|||||||
lang: Lang
|
lang: Lang
|
||||||
) {
|
) {
|
||||||
const [user, error] = await safeTry(
|
const [user, error] = await safeTry(
|
||||||
getVerifiedUser({
|
getBasicUser({
|
||||||
token: {
|
token: {
|
||||||
access_token: session.token.access_token,
|
access_token: session.token.access_token,
|
||||||
expires_at: session.token.expires_at ?? 0,
|
expires_at: session.token.expires_at ?? 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user