Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4b0b5e7
fix: make user email field nullable in schema and migration
mikeallisonJS Feb 3, 2026
abac660
refactor: rename User type to AuthenticatedUser and update related sc…
mikeallisonJS Feb 3, 2026
d86f07d
test: update User type to AuthenticatedUser in useJourneyQuery tests
mikeallisonJS Feb 3, 2026
fc5e6c8
fix: lint issues
autofix-ci[bot] Feb 3, 2026
7adad73
test: update User type to AuthenticatedUser in various component tests
mikeallisonJS Feb 3, 2026
b0ef999
test: remove User type from mock data in TeamManageWrapper tests
mikeallisonJS Feb 3, 2026
69c8b20
fix: lint issues
autofix-ci[bot] Feb 3, 2026
fc7326b
test: add test for creating anonymous user with null email in findOrF…
mikeallisonJS Feb 4, 2026
588cad8
refactor: update User type to include AnonymousUser and adjust relate…
mikeallisonJS Feb 4, 2026
5ec4146
refactor: update user handling to ensure only AuthenticatedUser types…
mikeallisonJS Feb 4, 2026
8578b80
test: update User type to AuthenticatedUser in various component tests
mikeallisonJS Feb 4, 2026
85eb72a
refactor: update User type to include AnonymousUser and adjust relate…
mikeallisonJS Feb 5, 2026
d408c98
refactor: enhance type safety for user checks in AccessDialog and Hos…
mikeallisonJS Feb 5, 2026
5d2ddfd
refactor: simplify user sign-in handling in UseThisTemplateButton
mikeallisonJS Feb 6, 2026
a4eae68
refactor: restructure UserRole handling and related schemas
mikeallisonJS Feb 6, 2026
da5cfa2
refactor: move getJourneyProfile query to modern journeys schema
mikeallisonJS Feb 6, 2026
09b28ad
feat: add quickStartTemplate seed to database seeding process
mikeallisonJS Feb 6, 2026
a4014b8
refactor: migrate adminJourneys query to modern journeys schema
mikeallisonJS Feb 7, 2026
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
77 changes: 35 additions & 42 deletions apis/api-gateway/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ type Mutation @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS
videoEditionDelete(id: ID!) : VideoEdition! @join__field(graph: API_MEDIA)
userImpersonate(email: String!) : String @join__field(graph: API_USERS)
createVerificationRequest(input: CreateVerificationRequestInput) : Boolean @join__field(graph: API_USERS)
validateEmail(email: String!, token: String!) : User @join__field(graph: API_USERS)
validateEmail(email: String!, token: String!) : AuthenticatedUser @join__field(graph: API_USERS)
}

type MutationSiteCreateSuccess @join__type(graph: API_ANALYTICS) {
Expand Down Expand Up @@ -711,21 +711,6 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
customDomains(teamId: ID!) : [CustomDomain!]! @join__field(graph: API_JOURNEYS)
hosts(teamId: ID!) : [Host!]! @join__field(graph: API_JOURNEYS)
integrations(teamId: ID!) : [Integration!]! @join__field(graph: API_JOURNEYS)
"""
returns all journeys that match the provided filters
If no team id is provided and template is not true then only returns journeys
where the user is not a member of a team but is an editor or owner of the
journey
"""
adminJourneys(
status: [JourneyStatus!]
template: Boolean
teamId: ID
"""
Use Last Active Team Id from JourneyProfile (if null will error)
"""
useLastActiveTeamId: Boolean
): [Journey!]! @join__field(graph: API_JOURNEYS)
adminJourneysReport(reportType: JourneysReportType!) : PowerBiEmbed @join__field(graph: API_JOURNEYS)
adminJourney(id: ID!, idType: IdType) : Journey! @join__field(graph: API_JOURNEYS)
journeys(where: JourneysFilter, options: JourneysQueryOptions) : [Journey!]! @join__field(graph: API_JOURNEYS)
Expand All @@ -734,7 +719,6 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
journeyCollections(teamId: ID!) : [JourneyCollection]! @join__field(graph: API_JOURNEYS)
journeyEventsConnection(journeyId: ID!, filter: JourneyEventsFilter, first: Int, after: String) : JourneyEventsConnection! @join__field(graph: API_JOURNEYS)
journeyEventsCount(journeyId: ID!, filter: JourneyEventsFilter) : Int! @join__field(graph: API_JOURNEYS)
getJourneyProfile: JourneyProfile @join__field(graph: API_JOURNEYS)
journeyTheme(journeyId: ID!) : JourneyTheme @join__field(graph: API_JOURNEYS)
"""
Get a list of Visitor Information by Journey
Expand Down Expand Up @@ -767,7 +751,6 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
teams: [Team!]! @join__field(graph: API_JOURNEYS)
team(id: ID!) : Team! @join__field(graph: API_JOURNEYS)
userInvites(journeyId: ID!) : [UserInvite!] @join__field(graph: API_JOURNEYS)
getUserRole: UserRole @join__field(graph: API_JOURNEYS)
userTeams(teamId: ID!, where: UserTeamFilterInput) : [UserTeam!]! @join__field(graph: API_JOURNEYS)
userTeam(id: ID!) : UserTeam! @join__field(graph: API_JOURNEYS)
userTeamInvites(teamId: ID!) : [UserTeamInvite!]! @join__field(graph: API_JOURNEYS)
Expand Down Expand Up @@ -797,6 +780,13 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
journeySimpleGet(id: ID!) : Json @join__field(graph: API_JOURNEYS_MODERN)
googleSheetsSyncs(filter: GoogleSheetsSyncsFilter!) : [GoogleSheetsSync!]! @join__field(graph: API_JOURNEYS_MODERN)
integrationGooglePickerToken(integrationId: ID!) : String! @join__field(graph: API_JOURNEYS_MODERN)
adminJourneys(
status: [JourneyStatus!]
template: Boolean
teamId: ID
useLastActiveTeamId: Boolean
): [Journey!]! @join__field(graph: API_JOURNEYS_MODERN)
getJourneyProfile: JourneyProfile @join__field(graph: API_JOURNEYS_MODERN)
"""
Returns a CSV formatted string with journey visitor export data including headers and visitor data with event information
"""
Expand Down Expand Up @@ -849,6 +839,7 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
"""
status: [JourneyStatus!]
): [TemplateFamilyStatsBreakdownResponse!] @join__field(graph: API_JOURNEYS_MODERN)
getUserRole: UserRole @join__field(graph: API_JOURNEYS_MODERN)
language(id: ID!, idType: LanguageIdType = databaseId) : Language @join__field(graph: API_LANGUAGES)
languages(offset: Int, limit: Int, where: LanguagesFilter, term: String) : [Language!]! @join__field(graph: API_LANGUAGES)
languagesCount(where: LanguagesFilter, term: String) : Int! @join__field(graph: API_LANGUAGES)
Expand Down Expand Up @@ -948,8 +939,8 @@ type Query @join__type(graph: API_ANALYTICS) @join__type(graph: API_JOURNEYS)
arclightApiKeys: [ArclightApiKey!]! @join__field(graph: API_MEDIA)
arclightApiKeyByKey(key: String!) : ArclightApiKey @join__field(graph: API_MEDIA)
me(input: MeInput) : User @join__field(graph: API_USERS)
user(id: ID!) : User @join__field(graph: API_USERS)
userByEmail(email: String!) : User @join__field(graph: API_USERS)
user(id: ID!) : AuthenticatedUser @join__field(graph: API_USERS)
userByEmail(email: String!) : AuthenticatedUser @join__field(graph: API_USERS)
}

type ButtonBlockSettings @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) {
Expand Down Expand Up @@ -1837,7 +1828,7 @@ type IntegrationGoogle implements Integration @join__type(graph: API_JOURNEYS)
id: ID!
team: Team!
type: IntegrationType!
user: User
user: AuthenticatedUser
accountEmail: String
}

Expand Down Expand Up @@ -1892,7 +1883,7 @@ type UserJourney @join__type(graph: API_JOURNEYS, key: "id") @join__type(graph:
userId: ID!
journeyId: ID!
role: UserJourneyRole!
user: User
user: AuthenticatedUser
"""
Date time of when the journey was first opened
"""
Expand Down Expand Up @@ -2181,7 +2172,7 @@ type UserInvite @join__type(graph: API_JOURNEYS, key: "id") @join__type(graph:
removedAt: DateTime
}

type User @join__type(graph: API_JOURNEYS, key: "id", extension: true) @join__type(graph: API_JOURNEYS_MODERN, key: "id", extension: true) @join__type(graph: API_LANGUAGES, key: "id", extension: true) @join__type(graph: API_MEDIA, key: "id", extension: true) @join__type(graph: API_USERS, key: "id") {
type AuthenticatedUser @join__type(graph: API_JOURNEYS, key: "id", extension: true) @join__type(graph: API_JOURNEYS_MODERN, key: "id", extension: true) @join__type(graph: API_LANGUAGES, key: "id", extension: true) @join__type(graph: API_MEDIA, key: "id", extension: true) @join__type(graph: API_USERS, key: "id") {
id: ID!
languageUserRoles: [LanguageRole!]! @join__field(graph: API_LANGUAGES)
mediaUserRoles: [MediaRole!]! @join__field(graph: API_MEDIA)
Expand All @@ -2193,10 +2184,8 @@ type User @join__type(graph: API_JOURNEYS, key: "id", extension: true) @join__t
emailVerified: Boolean! @join__field(graph: API_USERS)
}

type UserRole @join__type(graph: API_JOURNEYS, key: "id") @join__type(graph: API_JOURNEYS_MODERN, key: "id") {
type AnonymousUser @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) @join__type(graph: API_USERS) {
id: ID!
userId: ID!
roles: [Role!]
}

type UserTeamInvite @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) {
Expand Down Expand Up @@ -2554,6 +2543,12 @@ type TemplateFamilyStatsEventResponse @join__type(graph: API_JOURNEYS_MODERN) {
visitors: Int!
}

type UserRole @join__type(graph: API_JOURNEYS_MODERN, key: "id") {
id: ID!
userId: ID!
roles: [Role!]
}

type YouTube @join__type(graph: API_JOURNEYS_MODERN, key: "id primaryLanguageId", extension: true) {
id: ID!
primaryLanguageId: ID
Expand Down Expand Up @@ -2890,7 +2885,7 @@ type Playlist @join__type(graph: API_MEDIA) {
createdAt: DateTime!
updatedAt: DateTime!
slug: String!
owner: User!
owner: AuthenticatedUser!
items: [PlaylistItem!]!
}

Expand Down Expand Up @@ -3294,6 +3289,8 @@ interface Node @join__type(graph: API_JOURNEYS_MODERN) {

union MutationSiteCreateResult @join__type(graph: API_ANALYTICS) @join__unionMember(graph: API_ANALYTICS, member: "Error") @join__unionMember(graph: API_ANALYTICS, member: "MutationSiteCreateSuccess") = Error | MutationSiteCreateSuccess

union User @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) @join__type(graph: API_USERS) @join__unionMember(graph: API_JOURNEYS, member: "AuthenticatedUser") @join__unionMember(graph: API_JOURNEYS, member: "AnonymousUser") @join__unionMember(graph: API_JOURNEYS_MODERN, member: "AuthenticatedUser") @join__unionMember(graph: API_JOURNEYS_MODERN, member: "AnonymousUser") @join__unionMember(graph: API_USERS, member: "AuthenticatedUser") @join__unionMember(graph: API_USERS, member: "AnonymousUser") = AuthenticatedUser | AnonymousUser

union MediaVideo @join__type(graph: API_JOURNEYS_MODERN) @join__unionMember(graph: API_JOURNEYS_MODERN, member: "MuxVideo") @join__unionMember(graph: API_JOURNEYS_MODERN, member: "Video") @join__unionMember(graph: API_JOURNEYS_MODERN, member: "YouTube") = MuxVideo | Video | YouTube

union MutationPlaylistCreateResult @join__type(graph: API_MEDIA) @join__unionMember(graph: API_MEDIA, member: "ZodError") @join__unionMember(graph: API_MEDIA, member: "MutationPlaylistCreateSuccess") = ZodError | MutationPlaylistCreateSuccess
Expand Down Expand Up @@ -3628,14 +3625,6 @@ enum UserTeamRole @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURN
member @join__enumValue(graph: API_JOURNEYS) @join__enumValue(graph: API_JOURNEYS_MODERN)
}

enum Role @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) {
"""
User can create templates and
add them to template library
"""
publisher @join__enumValue(graph: API_JOURNEYS) @join__enumValue(graph: API_JOURNEYS_MODERN)
}

enum DeviceType @join__type(graph: API_JOURNEYS) @join__type(graph: API_JOURNEYS_MODERN) {
console @join__enumValue(graph: API_JOURNEYS) @join__enumValue(graph: API_JOURNEYS_MODERN)
mobile @join__enumValue(graph: API_JOURNEYS) @join__enumValue(graph: API_JOURNEYS_MODERN)
Expand Down Expand Up @@ -3728,21 +3717,29 @@ enum PlausibleEvent @join__type(graph: API_JOURNEYS_MODERN) {
journeyResponses @join__enumValue(graph: API_JOURNEYS_MODERN)
}

enum LanguageIdType @join__type(graph: API_LANGUAGES) {
databaseId @join__enumValue(graph: API_LANGUAGES)
bcp47 @join__enumValue(graph: API_LANGUAGES)
enum Role @join__type(graph: API_JOURNEYS_MODERN) {
publisher @join__enumValue(graph: API_JOURNEYS_MODERN)
}

enum LanguageRole @join__type(graph: API_LANGUAGES) {
publisher @join__enumValue(graph: API_LANGUAGES)
}

enum LanguageIdType @join__type(graph: API_LANGUAGES) {
databaseId @join__enumValue(graph: API_LANGUAGES)
bcp47 @join__enumValue(graph: API_LANGUAGES)
}

enum DefaultPlatform @join__type(graph: API_MEDIA) {
ios @join__enumValue(graph: API_MEDIA)
android @join__enumValue(graph: API_MEDIA)
web @join__enumValue(graph: API_MEDIA)
}

enum MediaRole @join__type(graph: API_MEDIA) {
publisher @join__enumValue(graph: API_MEDIA)
}

enum ImageAspectRatio @join__type(graph: API_MEDIA) {
hd @join__enumValue(graph: API_MEDIA)
banner @join__enumValue(graph: API_MEDIA)
Expand All @@ -3754,10 +3751,6 @@ enum MaxResolutionTier @join__type(graph: API_MEDIA) {
uhd @join__enumValue(graph: API_MEDIA)
}

enum MediaRole @join__type(graph: API_MEDIA) {
publisher @join__enumValue(graph: API_MEDIA)
}

enum SegmindModel @join__type(graph: API_MEDIA) {
sdxl1__0_txt2img @join__enumValue(graph: API_MEDIA)
kandinsky2__2_txt2img @join__enumValue(graph: API_MEDIA)
Expand Down
27 changes: 19 additions & 8 deletions apis/api-journeys-modern/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ interface Action {
parentBlock: Block!
}

type AnonymousUser
@shareable
{
id: ID!
}

type AuthenticatedUser
@key(fields: "id")
@extends
{
id: ID! @external
}

interface Block {
id: ID!
journeyId: ID!
Expand Down Expand Up @@ -697,7 +710,7 @@ type IntegrationGoogle implements Integration
type: IntegrationType!
team: Team!
accountEmail: String
user: User
user: AuthenticatedUser
}

input IntegrationGoogleCreateInput {
Expand Down Expand Up @@ -1702,6 +1715,8 @@ type Query {
journeySimpleGet(id: ID!): Json
googleSheetsSyncs(filter: GoogleSheetsSyncsFilter!): [GoogleSheetsSync!]!
integrationGooglePickerToken(integrationId: ID!): String!
adminJourneys(status: [JourneyStatus!], template: Boolean, teamId: ID, useLastActiveTeamId: Boolean): [Journey!]!
getJourneyProfile: JourneyProfile

"""
Returns a CSV formatted string with journey visitor export data including headers and visitor data with event information
Expand Down Expand Up @@ -1760,6 +1775,7 @@ type Query {
"""
status: [JourneyStatus!]
): [TemplateFamilyStatsBreakdownResponse!]
getUserRole: UserRole
}

type RadioOptionBlock implements Block
Expand Down Expand Up @@ -2250,12 +2266,7 @@ enum TypographyVariant {
overline
}

type User
@key(fields: "id")
@extends
{
id: ID! @external
}
union User = AuthenticatedUser | AnonymousUser

type UserAgent
@shareable
Expand Down Expand Up @@ -2290,7 +2301,7 @@ type UserJourney
role: UserJourneyRole!
openedAt: DateTime
journey: Journey
user: User
user: AuthenticatedUser
journeyNotification: JourneyNotification
}

Expand Down
3 changes: 3 additions & 0 deletions apis/api-journeys-modern/src/schema/authScopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ async function isTeamManager({

export interface AuthScopes {
isAuthenticated: boolean
isAnonymous: boolean
isPublisher: boolean
isValidInterop: boolean
}

export async function authScopes(context: Context) {
const defaultScopes = {
isAuthenticated: false,
isAnonymous: false,
isPublisher: false,
isValidInterop: false
}
Expand All @@ -91,6 +93,7 @@ export async function authScopes(context: Context) {
return {
...defaultScopes,
isAuthenticated: true,
isAnonymous: context.user.email == null,
isPublisher: context.currentRoles.includes('publisher'),
isInTeam: async (teamId: string) => await isInTeam({ context, teamId }),
isIntegrationOwner: async (integrationId: string) =>
Expand Down
1 change: 1 addition & 0 deletions apis/api-journeys-modern/src/schema/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const builder = new SchemaBuilder<{
AuthScopes: AuthScopes
AuthContexts: {
isAuthenticated: Extract<Context, { type: 'authenticated' }>
isAnonymous: Extract<Context, { type: 'authenticated' }>
isInTeam: Extract<Context, { type: 'authenticated' }>
isIntegrationOwner: Extract<Context, { type: 'authenticated' }>
isTeamManager: Extract<Context, { type: 'authenticated' }>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { builder } from '../../builder'
import { UserRef } from '../../user'
import { AuthenticatedUserRef } from '../../user'
import { IntegrationRef } from '../integration'

export const IntegrationGoogleRef = builder.prismaObject('Integration', {
Expand All @@ -11,7 +11,7 @@ export const IntegrationGoogleRef = builder.prismaObject('Integration', {
accountEmail: t.exposeString('accountEmail', { nullable: true }),
team: t.relation('team', { nullable: false }),
user: t.field({
type: UserRef,
type: AuthenticatedUserRef,
nullable: true,
resolve: async (integration) => {
if (integration.userId == null) return null
Expand Down
Loading