You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
Allow more characters in device IDs
This commit is contained in:
@@ -70,13 +70,35 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
const fn valid_device_chars(c: char) -> bool {
|
||||
// This matches the regex in the policy
|
||||
c.is_ascii_alphanumeric()
|
||||
|| c == '.'
|
||||
|| c == '_'
|
||||
|| c == '~'
|
||||
|| c == '!'
|
||||
|| c == '$'
|
||||
|| c == '&'
|
||||
|| c == '\''
|
||||
|| c == '('
|
||||
|| c == ')'
|
||||
|| c == '*'
|
||||
|| c == '+'
|
||||
|| c == ','
|
||||
|| c == ';'
|
||||
|| c == '='
|
||||
|| c == ':'
|
||||
|| c == '@'
|
||||
|| c == '/'
|
||||
|| c == '-'
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Device {
|
||||
type Error = InvalidDeviceID;
|
||||
|
||||
/// Create a [`Device`] out of an ID, validating the ID has the right shape
|
||||
fn try_from(id: String) -> Result<Self, Self::Error> {
|
||||
// This matches the regex in the policy
|
||||
if !id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') {
|
||||
if !id.chars().all(valid_device_chars) {
|
||||
return Err(InvalidDeviceID::InvalidCharacters);
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@ import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as ResetCrossSigningImport } from './routes/reset-cross-signing'
|
||||
import { Route as AccountImport } from './routes/_account'
|
||||
import { Route as AccountIndexImport } from './routes/_account.index'
|
||||
import { Route as DevicesIdImport } from './routes/devices.$id'
|
||||
import { Route as DevicesSplatImport } from './routes/devices.$'
|
||||
import { Route as ClientsIdImport } from './routes/clients.$id'
|
||||
import { Route as AccountSessionsIndexImport } from './routes/_account.sessions.index'
|
||||
import { Route as EmailsIdVerifyImport } from './routes/emails.$id.verify'
|
||||
@@ -38,8 +38,8 @@ const AccountIndexRoute = AccountIndexImport.update({
|
||||
getParentRoute: () => AccountRoute,
|
||||
} as any)
|
||||
|
||||
const DevicesIdRoute = DevicesIdImport.update({
|
||||
path: '/devices/$id',
|
||||
const DevicesSplatRoute = DevicesSplatImport.update({
|
||||
path: '/devices/$',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
@@ -84,8 +84,8 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ClientsIdImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/devices/$id': {
|
||||
preLoaderRoute: typeof DevicesIdImport
|
||||
'/devices/$': {
|
||||
preLoaderRoute: typeof DevicesSplatImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/_account/': {
|
||||
@@ -122,7 +122,7 @@ export const routeTree = rootRoute.addChildren([
|
||||
]),
|
||||
ResetCrossSigningRoute,
|
||||
ClientsIdRoute,
|
||||
DevicesIdRoute,
|
||||
DevicesSplatRoute,
|
||||
EmailsIdVerifyRoute,
|
||||
])
|
||||
|
||||
|
@@ -71,8 +71,8 @@ export const Route = createRootRouteWithContext<{
|
||||
case "org.matrix.session_view":
|
||||
if (search.device_id)
|
||||
throw redirect({
|
||||
to: "/devices/$id",
|
||||
params: { id: search.device_id },
|
||||
to: "/devices/$",
|
||||
params: { _splat: search.device_id },
|
||||
});
|
||||
throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } });
|
||||
|
||||
@@ -80,8 +80,8 @@ export const Route = createRootRouteWithContext<{
|
||||
case "org.matrix.session_end":
|
||||
if (search.device_id)
|
||||
throw redirect({
|
||||
to: "/devices/$id",
|
||||
params: { id: search.device_id },
|
||||
to: "/devices/$",
|
||||
params: { _splat: search.device_id },
|
||||
});
|
||||
throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } });
|
||||
|
||||
|
@@ -42,7 +42,7 @@ const QUERY = graphql(/* GraphQL */ `
|
||||
}
|
||||
`);
|
||||
|
||||
export const Route = createFileRoute("/devices/$id")({
|
||||
export const Route = createFileRoute("/devices/$")({
|
||||
async loader({ context, params, abortController: { signal } }) {
|
||||
const viewer = await context.client.query(
|
||||
CURRENT_VIEWER_QUERY,
|
||||
@@ -57,7 +57,7 @@ export const Route = createFileRoute("/devices/$id")({
|
||||
const result = await context.client.query(
|
||||
QUERY,
|
||||
{
|
||||
deviceId: params.id,
|
||||
deviceId: params._splat,
|
||||
userId: viewer.data.viewer.id,
|
||||
},
|
||||
{ fetchOptions: { signal } },
|
||||
@@ -78,7 +78,7 @@ export const Route = createFileRoute("/devices/$id")({
|
||||
|
||||
function NotFound(): React.ReactElement {
|
||||
const { t } = useTranslation();
|
||||
const { id: deviceId } = Route.useParams();
|
||||
const { _splat: deviceId } = Route.useParams();
|
||||
return (
|
||||
<Layout>
|
||||
<Alert
|
@@ -62,7 +62,7 @@ allowed_scope("urn:mas:admin") {
|
||||
allowed_scope(scope) {
|
||||
# Grant access to the C-S API only if there is a user
|
||||
interactive_grant_type(input.grant_type)
|
||||
regex.match("urn:matrix:org.matrix.msc2967.client:device:[A-Za-z0-9-]{10,}", scope)
|
||||
regex.match("^urn:matrix:org.matrix.msc2967.client:device:[A-Za-z0-9._~!$&'()*+,;=:@/-]{10,}$", scope)
|
||||
}
|
||||
|
||||
allowed_scope("urn:matrix:org.matrix.msc2967.client:api:*") {
|
||||
|
Reference in New Issue
Block a user