Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show header when not in iframe #241

Merged
merged 5 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions src/backend/error-message-to-user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function errorMessageToUser(errorDetails: string) {
return `Es ist leider ein Fehler aufgetreten. Bitte wende dich an [email protected] mit dieser Fehlermeldung: ${errorDetails}`
}
75 changes: 51 additions & 24 deletions src/backend/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getMariaDB } from './mariadb'
import * as media from './media-route-handlers'
import { logger } from '../utils/logger'
import { IdToken } from './types/idtoken'
import { errorMessageToUser } from './error-message-to-user'

const ltijsKey = config.LTIJS_KEY

Expand Down Expand Up @@ -142,9 +143,7 @@ const setup = async () => {
_: Request,
res: Response
) {
const resourceLinkId: string = idToken.platformContext.resource.id
const custom: unknown = idToken.platformContext.custom

const custom: unknown = idToken.platformContext?.custom
const expectedCustomType = t.intersection([
t.type({
getContentApiUrl: t.string,
Expand All @@ -160,16 +159,23 @@ const setup = async () => {
version: t.string,
}),
])

if (!expectedCustomType.is(custom)) {
res
.status(400)
.send(
`Unexpected type of LTI 'custom' claim. Got ${JSON.stringify(custom)}`
errorMessageToUser(
`Unexpected type of LTI 'custom' claim. Got ${JSON.stringify(custom)}`
)
)
return
}

const resourceLinkId = idToken.platformContext?.resource?.id
if (!resourceLinkId) {
res.status(400).send(errorMessageToUser('resource link id missing'))
return
}

const edusharingNodeId = custom.nodeId

const entityId = await getEntityId()
Expand All @@ -196,23 +202,32 @@ const setup = async () => {
const accessToken = createAccessToken(editorMode, entityId, ltijsKey)

const ltik = res.locals.ltik
const title = idToken.platformContext?.resource?.title
const contextTitle = idToken.platformContext?.context?.title

const searchParams = createSearchParams({ ltik, accessToken, idToken })
const searchParams = createSearchParams({
ltik,
accessToken,
resourceLinkId,
title,
contextTitle,
})

return ltijs.redirect(res, `/app?${searchParams.toString()}`)
}

async function onConnectDefault(
idToken: IdToken,
req: Request,
res: Response
) {
// Get customId from lti custom claim or alternatively search query parameters
// Using search query params is suggested by ltijs, see: https://github.com/Cvmcosta/ltijs/issues/100#issuecomment-832284300
const customId = idToken.platformContext.custom.id ?? req.query.id
if (!customId) return res.send('Missing customId!')
async function onConnectDefault(idToken: IdToken, _: Request, res: Response) {
const customId = idToken.platformContext?.custom?.id
if (!customId) {
res.status(400).send(errorMessageToUser('custom id missing'))
return
}

const resourceLinkId: string = idToken.platformContext.resource.id
const resourceLinkId = idToken.platformContext?.resource?.id
if (!resourceLinkId) {
res.status(400).send(errorMessageToUser('resource link id missing'))
return
}

logger.info('ltijs.onConnect -> idToken: ', idToken)

Expand All @@ -235,7 +250,7 @@ const setup = async () => {
)

if (!entity) {
res.send('<div>Dieser Inhalt wurde nicht gefunden.</div>')
res.send(errorMessageToUser('Content not found in database'))
return
}

Expand All @@ -255,7 +270,7 @@ const setup = async () => {
// This role is sent in the itslearning library and we disallow editing there for now
// 'membership#Member',
]
const courseMembershipRole = idToken.platformContext.roles?.find((role) =>
const courseMembershipRole = idToken.platformContext?.roles?.find((role) =>
role.includes('membership#')
)
const editorMode =
Expand All @@ -277,28 +292,40 @@ const setup = async () => {
}

const ltik = res.locals.ltik
const title = idToken.platformContext?.resource?.title
const contextTitle = idToken.platformContext?.context?.title

const searchParams = createSearchParams({ ltik, accessToken, idToken })
const searchParams = createSearchParams({
ltik,
accessToken,
resourceLinkId,
contextTitle,
title,
})

return ltijs.redirect(res, `/app?${searchParams.toString()}`)
}

function createSearchParams({
ltik,
accessToken,
idToken,
resourceLinkId,
contextTitle,
title,
}: {
ltik: string
accessToken: string
idToken: IdToken
resourceLinkId: string
contextTitle?: string
title?: string
}) {
const searchParams = new URLSearchParams()
searchParams.append('accessToken', accessToken)
searchParams.append('resourceLinkId', idToken.platformContext.resource.id)
searchParams.append('resourceLinkId', resourceLinkId)
searchParams.append('testingSecret', config.SERLO_EDITOR_TESTING_SECRET)
searchParams.append('ltik', ltik)
searchParams.append('contextTitle', idToken.platformContext.context.title)
searchParams.append('title', idToken.platformContext.resource.title)
searchParams.append('contextTitle', contextTitle ?? '')
searchParams.append('title', title ?? '')

return searchParams
}
Expand Down
16 changes: 8 additions & 8 deletions src/backend/types/idtoken.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Hard coded type because the type provided by @types/ltijs is outdated
// TODO: Use type provided by ltijs instead once it is included or extend this one with additional properties
export interface IdToken {
platformContext: {
custom: {
id: string
platformContext?: {
custom?: {
id?: string
}
resource: {
id: string
title: string
resource?: {
id?: string
title?: string
}
roles?: string[]
context: {
title: string
context?: {
title?: string
}
}
iss: string
Expand Down