feat: (Web-210) Added encryption for my-booking Urls
This commit is contained in:
@@ -31,6 +31,8 @@ SEAMLESS_LOGOUT_FI="http://www.example.fi/updatelogout?newweb=1"
|
|||||||
SEAMLESS_LOGOUT_NO="http://www.example.no/updatelogout?newweb=1"
|
SEAMLESS_LOGOUT_NO="http://www.example.no/updatelogout?newweb=1"
|
||||||
SEAMLESS_LOGOUT_SV="http://www.example.sv/updatelogout?newweb=1"
|
SEAMLESS_LOGOUT_SV="http://www.example.sv/updatelogout?newweb=1"
|
||||||
WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="
|
WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="
|
||||||
|
BOOKING_ENCRYPTION_KEY=za2paS0x
|
||||||
|
NODE_OPTIONS=--openssl-legacy-provider
|
||||||
|
|
||||||
PUBLIC_URL="http://localhost:3000"
|
PUBLIC_URL="http://localhost:3000"
|
||||||
AUTH_URL="$PUBLIC_URL/api/web/auth"
|
AUTH_URL="$PUBLIC_URL/api/web/auth"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { dt } from "@/lib/dt"
|
|||||||
import { CalendarIcon } from "@/components/Icons"
|
import { CalendarIcon } from "@/components/Icons"
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||||
|
|
||||||
import styles from "./stay.module.css"
|
import styles from "./stay.module.css"
|
||||||
@@ -10,7 +11,9 @@ import styles from "./stay.module.css"
|
|||||||
import type { StayCardProps } from "@/types/components/myPages/stays/stayCard"
|
import type { StayCardProps } from "@/types/components/myPages/stays/stayCard"
|
||||||
|
|
||||||
export default function StayCard({ stay, lang }: StayCardProps) {
|
export default function StayCard({ stay, lang }: StayCardProps) {
|
||||||
const { checkinDate, checkoutDate, hotelInformation } = stay.attributes
|
const { checkinDate, checkoutDate, hotelInformation, bookingUrl } =
|
||||||
|
stay.attributes
|
||||||
|
|
||||||
const arrival = dt(checkinDate).locale(lang)
|
const arrival = dt(checkinDate).locale(lang)
|
||||||
const arrivalDate = arrival.format("DD MMM")
|
const arrivalDate = arrival.format("DD MMM")
|
||||||
const arrivalDateTime = arrival.format("YYYY-MM-DD")
|
const arrivalDateTime = arrival.format("YYYY-MM-DD")
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export const getStaysSchema = z.object({
|
|||||||
checkinDate: z.string(),
|
checkinDate: z.string(),
|
||||||
checkoutDate: z.string(),
|
checkoutDate: z.string(),
|
||||||
isWebAppOrigin: z.boolean(),
|
isWebAppOrigin: z.boolean(),
|
||||||
|
bookingUrl: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
relationships: z.object({
|
relationships: z.object({
|
||||||
hotel: z.object({
|
hotel: z.object({
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
getUserInputSchema,
|
getUserInputSchema,
|
||||||
staysInput,
|
staysInput,
|
||||||
} from "./input"
|
} from "./input"
|
||||||
|
import encryptValue from "../utils/encryptValue"
|
||||||
import {
|
import {
|
||||||
getCreditCardsSchema,
|
getCreditCardsSchema,
|
||||||
getFriendTransactionsSchema,
|
getFriendTransactionsSchema,
|
||||||
@@ -212,6 +213,61 @@ export const userQueryRouter = router({
|
|||||||
? verifiedData.data.links.offset
|
? verifiedData.data.links.offset
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
|
// Tenporary till we have user name in ctx session data
|
||||||
|
// ----
|
||||||
|
const apiResponseUser = await api.get(api.endpoints.v1.profile, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!apiResponseUser.ok) {
|
||||||
|
// switch (apiResponseUser.status) {
|
||||||
|
// case 400:
|
||||||
|
// throw badRequestError(apiResponseUser)
|
||||||
|
// case 401:
|
||||||
|
// throw unauthorizedError(apiResponseUser)
|
||||||
|
// case 403:
|
||||||
|
// throw forbiddenError(apiResponseUser)
|
||||||
|
// default:
|
||||||
|
// throw internalServerError(apiResponseUser)
|
||||||
|
// }
|
||||||
|
console.info(`API Response Failed - Getting User`)
|
||||||
|
console.info(`User: (${JSON.stringify(ctx.session.user)})`)
|
||||||
|
console.error(apiResponse)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiJsonUser = await apiResponse.json()
|
||||||
|
if (!apiJson.data?.attributes) {
|
||||||
|
// throw notFound(apiJson)
|
||||||
|
console.error(
|
||||||
|
`User has no data - (user: ${JSON.stringify(ctx.session.user)})`
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifiedDataUser = getUserSchema.safeParse(apiJsonUser.data.attributes)
|
||||||
|
if (!verifiedDataUser.success) {
|
||||||
|
console.info(
|
||||||
|
`Failed to validate User - (User: ${JSON.stringify(ctx.session.user)})`
|
||||||
|
)
|
||||||
|
console.error(verifiedDataUser.error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
verifiedData.data.data.forEach((stay) => {
|
||||||
|
const originalString =
|
||||||
|
stay.attributes.confirmationNumber.toString() +
|
||||||
|
"," +
|
||||||
|
verifiedDataUser.data.lastName
|
||||||
|
let bookingUrl = encryptValue(originalString)
|
||||||
|
stay.attributes.bookingUrl =
|
||||||
|
"/hotelreservation/my-booking?RefId=" + bookingUrl
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: verifiedData.data.data,
|
data: verifiedData.data.data,
|
||||||
nextCursor,
|
nextCursor,
|
||||||
@@ -272,6 +328,61 @@ export const userQueryRouter = router({
|
|||||||
? verifiedData.data.links.offset
|
? verifiedData.data.links.offset
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
|
// Tenporary till we have user name in ctx session data
|
||||||
|
// ----
|
||||||
|
const apiResponseUser = await api.get(api.endpoints.v1.profile, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!apiResponseUser.ok) {
|
||||||
|
// switch (apiResponseUser.status) {
|
||||||
|
// case 400:
|
||||||
|
// throw badRequestError(apiResponseUser)
|
||||||
|
// case 401:
|
||||||
|
// throw unauthorizedError(apiResponseUser)
|
||||||
|
// case 403:
|
||||||
|
// throw forbiddenError(apiResponseUser)
|
||||||
|
// default:
|
||||||
|
// throw internalServerError(apiResponseUser)
|
||||||
|
// }
|
||||||
|
console.info(`API Response Failed - Getting Upcoming Stays`)
|
||||||
|
console.info(`User: (${JSON.stringify(ctx.session.user)})`)
|
||||||
|
console.error(apiResponse)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiJsonUser = await apiResponse.json()
|
||||||
|
if (!apiJson.data?.attributes) {
|
||||||
|
// throw notFound(apiJson)
|
||||||
|
console.error(
|
||||||
|
`User has no data - (user: ${JSON.stringify(ctx.session.user)})`
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifiedDataUser = getUserSchema.safeParse(apiJsonUser.data.attributes)
|
||||||
|
if (!verifiedDataUser.success) {
|
||||||
|
console.info(
|
||||||
|
`Failed to validate User - (User: ${JSON.stringify(ctx.session.user)})`
|
||||||
|
)
|
||||||
|
console.error(verifiedDataUser.error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
verifiedData.data.data.forEach((stay) => {
|
||||||
|
const originalString =
|
||||||
|
stay.attributes.confirmationNumber.toString() +
|
||||||
|
"," +
|
||||||
|
verifiedDataUser.data.lastName
|
||||||
|
let bookingUrl = encryptValue(originalString)
|
||||||
|
stay.attributes.bookingUrl =
|
||||||
|
"/hotelreservation/my-booking?RefId=" + bookingUrl
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: verifiedData.data.data,
|
data: verifiedData.data.data,
|
||||||
nextCursor,
|
nextCursor,
|
||||||
|
|||||||
18
server/routers/utils/encryptValue.ts
Normal file
18
server/routers/utils/encryptValue.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import crypto from "crypto"
|
||||||
|
|
||||||
|
export default function encryptValue(originalString: string) {
|
||||||
|
const encryptionKey = process.env.BOOKING_ENCRYPTION_KEY ?? ""
|
||||||
|
const bufferKey = Buffer.from(encryptionKey, "utf8")
|
||||||
|
let cipher = crypto.createCipheriv("DES-ECB", bufferKey, null)
|
||||||
|
cipher.setAutoPadding(false)
|
||||||
|
let bufferString = Buffer.from(originalString, "utf8")
|
||||||
|
let paddingSize = bufferKey.length - (bufferString.length % bufferKey.length)
|
||||||
|
let paddedStr = Buffer.concat([bufferString, Buffer.alloc(paddingSize, 0)])
|
||||||
|
let encryptedValue = cipher
|
||||||
|
.update(paddedStr)
|
||||||
|
.toString("base64")
|
||||||
|
.replace(/\+/g, "-")
|
||||||
|
cipher.final()
|
||||||
|
|
||||||
|
return encryptedValue
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user