mirror of
https://github.com/suitenumerique/meet.git
synced 2026-11-13 13:59:19 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f8f5d0386 | |||
| 25122deba2 |
@@ -37,6 +37,8 @@ and this project adheres to
|
||||
- 🔒️(agents) upgrade python to 3.14.10 to fix CVE-2026-109518
|
||||
- 🔒️(docker) upgrade musl-utils to 1.2.6-r3 to fix CVE-2026-107891
|
||||
- ♿️(frontend) close the invite dialog with the Escape key #1916
|
||||
- 🔒️(docker) move frontend to nginx/nginx-unprivileged image
|
||||
- 🐛(frontend) accept meeting links with query params in join dialog
|
||||
|
||||
## [1.37.0] - 2026-11-01
|
||||
|
||||
|
||||
@@ -58,19 +58,13 @@ RUN npx webpack --mode production
|
||||
|
||||
|
||||
# ---- Front-end image ----
|
||||
FROM nginxinc/nginx-unprivileged:1.30.6-alpine3.24 AS frontend-production
|
||||
FROM nginx/nginx-unprivileged:1.30.6-alpine3.24 AS frontend-production
|
||||
|
||||
USER root
|
||||
RUN apk upgrade --no-cache libexpat && \
|
||||
apk add --no-cache --upgrade 'pcre2>=10.49-r0' 'tiff>=4.7.2-r0' \
|
||||
'libx11>=1.8.14-r0' 'ca-certificates>=20261020-r0' \
|
||||
'brotli-libs>=1.2.1-r0' 'musl-utils>=1.2.6-r3' && \
|
||||
apk del curl && \
|
||||
RUN apk del curl && \
|
||||
rm -f /usr/share/nginx/html/50x.html
|
||||
USER nginx
|
||||
|
||||
USER nginx
|
||||
|
||||
# Un-privileged user running the application
|
||||
ARG DOCKER_USER
|
||||
USER ${DOCKER_USER}
|
||||
|
||||
@@ -47,14 +47,10 @@ ENV VITE_MEDIA_BASE_URL=${VITE_MEDIA_BASE_URL}
|
||||
RUN npm run build
|
||||
|
||||
# ---- Front-end image ----
|
||||
FROM nginxinc/nginx-unprivileged:1.30.6-alpine3.24 AS frontend-production
|
||||
FROM nginx/nginx-unprivileged:1.30.6-alpine3.24 AS frontend-production
|
||||
|
||||
USER root
|
||||
RUN apk upgrade --no-cache libexpat && \
|
||||
apk add --no-cache --upgrade 'pcre2>=10.49-r0' 'tiff>=4.7.2-r0' \
|
||||
'libx11>=1.8.14-r0' 'ca-certificates>=20261020-r0' \
|
||||
'brotli-libs>=1.2.1-r0' 'musl-utils>=1.2.6-r3' && \
|
||||
apk del curl && \
|
||||
RUN apk del curl && \
|
||||
rm -f /usr/share/nginx/html/50x.html
|
||||
USER nginx
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Field, Ul, H, P, Form, Dialog } from '@/primitives'
|
||||
import { navigateTo } from '@/navigation/navigateTo'
|
||||
import { isRoomValid } from '@/features/rooms'
|
||||
import { extractRoomId } from '@/features/rooms'
|
||||
|
||||
export const JoinMeetingDialog = () => {
|
||||
const { t } = useTranslation('home')
|
||||
|
||||
const handleSubmit = (data: { roomId?: FormDataEntryValue }) => {
|
||||
const roomId = (data.roomId as string)
|
||||
.trim()
|
||||
.replace(`${window.location.origin}/`, '')
|
||||
navigateTo('room', roomId)
|
||||
const extracted = extractRoomId(data.roomId as string)
|
||||
if (!extracted) return
|
||||
navigateTo('room', `${extracted.roomId}${extracted.suffix}`)
|
||||
}
|
||||
|
||||
const validateRoomId = (value: string) => {
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed) return null
|
||||
return !isRoomValid(trimmed) ? (
|
||||
return !extractRoomId(trimmed) ? (
|
||||
<>
|
||||
<p>{t('joinInputError')}</p>
|
||||
<Ul>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export {
|
||||
roomIdPattern,
|
||||
isRoomValid,
|
||||
extractRoomId,
|
||||
flexibleRoomIdPattern,
|
||||
} from './utils/isRoomValid'
|
||||
export { generateRoomId } from './utils/generateRoomId'
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { normalizeRoomId } from './isRoomValid'
|
||||
import { extractRoomId, normalizeRoomId } from './isRoomValid'
|
||||
|
||||
describe('extractRoomId', () => {
|
||||
const origin = 'https://meet.example.com'
|
||||
|
||||
const plain = { roomId: 'abc-defg-hij', suffix: '' }
|
||||
|
||||
it('accepts a bare room id', () => {
|
||||
expect(extractRoomId('abc-defg-hij', origin)).toEqual(plain)
|
||||
expect(extractRoomId(' abc-defg-hij ', origin)).toEqual(plain)
|
||||
})
|
||||
|
||||
it('accepts a meeting URL on this origin', () => {
|
||||
expect(extractRoomId(`${origin}/abc-defg-hij`, origin)).toEqual(plain)
|
||||
expect(extractRoomId(`${origin}/abc-defg-hij/`, origin)).toEqual(plain)
|
||||
})
|
||||
|
||||
it('keeps query strings and fragments in the suffix', () => {
|
||||
expect(
|
||||
extractRoomId(`${origin}/abc-defg-hij?from=outlook-addin`, origin)
|
||||
).toEqual({ roomId: 'abc-defg-hij', suffix: '?from=outlook-addin' })
|
||||
expect(
|
||||
extractRoomId(
|
||||
`${origin}/abc-defg-hij/?utm_source=mail&utm_medium=email#x`,
|
||||
origin
|
||||
)
|
||||
).toEqual({
|
||||
roomId: 'abc-defg-hij',
|
||||
suffix: '?utm_source=mail&utm_medium=email#x',
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects other origins and invalid ids', () => {
|
||||
expect(
|
||||
extractRoomId('https://evil.example/abc-defg-hij', origin)
|
||||
).toBeNull()
|
||||
expect(extractRoomId(`${origin}/not-a-room`, origin)).toBeNull()
|
||||
expect(extractRoomId(`${origin}/abc-defg-hij/extra`, origin)).toBeNull()
|
||||
expect(extractRoomId('abc-defg-hij?from=x', origin)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('normalizeRoomId', () => {
|
||||
it('lowercases and re-inserts the hyphens of a ten-letter id', () => {
|
||||
|
||||
@@ -10,6 +10,28 @@ export const isRoomValid = (roomIdOrUrl: string) =>
|
||||
roomRegex.test(roomIdOrUrl) ||
|
||||
new RegExp(`^${window.location.origin}/${roomIdPattern}$`).test(roomIdOrUrl)
|
||||
|
||||
export const extractRoomId = (
|
||||
input: string,
|
||||
origin: string = window.location.origin
|
||||
): { roomId: string; suffix: string } | null => {
|
||||
const value = input.trim()
|
||||
if (roomRegex.test(value)) return { roomId: value, suffix: '' }
|
||||
|
||||
let url: URL
|
||||
try {
|
||||
url = new URL(value)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
if (url.origin !== origin) return null
|
||||
|
||||
const path = url.pathname.slice(1)
|
||||
const roomId = path.endsWith('/') ? path.slice(0, -1) : path
|
||||
return roomRegex.test(roomId)
|
||||
? { roomId, suffix: `${url.search}${url.hash}` }
|
||||
: null
|
||||
}
|
||||
|
||||
export const normalizeRoomId = (roomId: string) => {
|
||||
const cleanId = roomId.toLowerCase().replace(/-/g, '')
|
||||
if (cleanId.length === 10) {
|
||||
|
||||
Reference in New Issue
Block a user