mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(api): validate push and domain verification targets (#2346)
This commit is contained in:
1 parent
693aec2b4d
commit
1d84689b45
5 files changed
+75
-3
No files matched your search
@@ -11,6 +11,7 @@ import {
|
||||
Int32Type,
|
||||
withOpenApiType,
|
||||
} from '@fluxer/schema/src/primitives/SchemaPrimitives';
|
||||
import {HostnameType} from '@fluxer/schema/src/primitives/UrlValidators';
|
||||
import {z} from 'zod';
|
||||
|
||||
const ConnectionTypeSchema = withOpenApiType(
|
||||
@@ -62,7 +63,7 @@ export type VerifyAndCreateConnectionRequest = z.infer<typeof VerifyAndCreateCon
|
||||
|
||||
export const CreateConnectionRequest = z.object({
|
||||
type: ConnectionTypeSchema.describe('The type of connection to create'),
|
||||
identifier: z.string().min(1).max(253).describe('The connection identifier (handle or domain)'),
|
||||
identifier: HostnameType.describe('The connection identifier (handle or domain)'),
|
||||
visibility_flags: Int32Type.optional().describe('Bitfield controlling who can see this connection'),
|
||||
});
|
||||
|
||||
|
||||
@@ -514,6 +514,13 @@ export const RegisterMobileDeviceRequest = z
|
||||
})
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.platform !== 'android_unified_push') return;
|
||||
if (!URLType.safeParse(value.token).success) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['token'],
|
||||
message: 'UnifiedPush registrations require a valid endpoint URL',
|
||||
});
|
||||
}
|
||||
if (!value.encryption_key) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
|
||||
@@ -7,6 +7,7 @@ import {z} from 'zod';
|
||||
|
||||
const PROTOCOLS = ['http', 'https'];
|
||||
const FILENAME_SAFE_REGEX = /^[\p{L}\p{N}\p{M}_.-]+$/u;
|
||||
const HOSTNAME_LABEL_REGEX = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
||||
const URL_VALIDATOR_OPTIONS = {
|
||||
require_protocol: true,
|
||||
require_host: true,
|
||||
@@ -50,6 +51,27 @@ function createUrlSchema() {
|
||||
);
|
||||
}
|
||||
|
||||
export function isFqdnHostname(hostname: string): boolean {
|
||||
if (!hostname || hostname.length > 253 || !hostname.includes('.')) {
|
||||
return false;
|
||||
}
|
||||
const labels = hostname.split('.');
|
||||
for (const label of labels) {
|
||||
if (!label || label.length > 63 || !HOSTNAME_LABEL_REGEX.test(label)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !/^\d+$/.test(labels[labels.length - 1]);
|
||||
}
|
||||
|
||||
export const HostnameType = z
|
||||
.string()
|
||||
.transform((value) => {
|
||||
const trimmed = value.trim().toLowerCase();
|
||||
return trimmed.endsWith('.') ? trimmed.slice(0, -1) : trimmed;
|
||||
})
|
||||
.refine(isFqdnHostname, ValidationErrorCodes.INVALID_FORMAT);
|
||||
|
||||
export const URLType = createUrlSchema();
|
||||
export const AttachmentURLType = z
|
||||
.string()
|
||||
|
||||
Reference in new issue
Block a user