mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-09 13:51:57 -04:00
feat(commons): add DTOs
Moving the DTOs to commons so frontend and backend use the same types. Also introducing zod for validation. Co-authored-by: Erik Michelson <github@erik.michelson.eu> Signed-off-by: Erik Michelson <github@erik.michelson.eu> Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
aa87ff35b3
commit
4b5bf870f2
65 changed files with 1211 additions and 48 deletions
20
commons/src/dtos/alias/alias-create.dto.ts
Normal file
20
commons/src/dtos/alias/alias-create.dto.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const AliasCreateSchema = z
|
||||
.object({
|
||||
noteIdOrAlias: z
|
||||
.string()
|
||||
.describe(
|
||||
'The note id, which identifies the note the alias should be added to',
|
||||
),
|
||||
newAlias: z.string().describe('The new alias'),
|
||||
})
|
||||
.describe('DTO for creating a new alias')
|
||||
|
||||
export type AliasCreateDto = z.infer<typeof AliasCreateSchema>
|
17
commons/src/dtos/alias/alias-update.dto.ts
Normal file
17
commons/src/dtos/alias/alias-update.dto.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const AliasUpdateSchema = z
|
||||
.object({
|
||||
primaryAlias: z
|
||||
.literal(true)
|
||||
.describe('Whether the alias should become the primary alias or not'),
|
||||
})
|
||||
.describe('DTO for making one alias primary')
|
||||
|
||||
export type AliasUpdateDto = z.infer<typeof AliasUpdateSchema>
|
21
commons/src/dtos/alias/alias.dto.ts
Normal file
21
commons/src/dtos/alias/alias.dto.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const AliasSchema = z
|
||||
.object({
|
||||
name: z.string().describe('The name of the alias'),
|
||||
primaryAlias: z.boolean().describe('Is the alias the primary alias or not'),
|
||||
noteId: z
|
||||
.string()
|
||||
.describe('The public id of the note the alias is associated with'),
|
||||
})
|
||||
.describe(
|
||||
'The alias of a note. A note can have multiple of these. Only one can be the primary alias.',
|
||||
)
|
||||
|
||||
export type AliasDto = z.infer<typeof AliasSchema>
|
9
commons/src/dtos/alias/index.ts
Normal file
9
commons/src/dtos/alias/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './alias.dto.js'
|
||||
export * from './alias-create.dto.js'
|
||||
export * from './alias-update.dto.js'
|
26
commons/src/dtos/api-token/api-token-create.dto.ts
Normal file
26
commons/src/dtos/api-token/api-token-create.dto.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
const nowPlusTwoYears = (): Date => {
|
||||
const date = new Date()
|
||||
date.setFullYear(date.getFullYear() + 2)
|
||||
return date
|
||||
}
|
||||
|
||||
export const ApiTokenCreateSchema = z
|
||||
.object({
|
||||
label: z.string().describe('Label for the new token'),
|
||||
validUntil: z.coerce
|
||||
.date()
|
||||
.max(nowPlusTwoYears())
|
||||
.describe(
|
||||
'Expiry date for the new token. Should be at max two years in the future.',
|
||||
),
|
||||
})
|
||||
.describe('DTO for creating a new API access token')
|
||||
|
||||
export type ApiTokenCreateDto = z.infer<typeof ApiTokenCreateSchema>
|
17
commons/src/dtos/api-token/api-token-with-secret.dto.ts
Normal file
17
commons/src/dtos/api-token/api-token-with-secret.dto.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
import { ApiTokenSchema } from './api-token.dto.js'
|
||||
|
||||
export const ApiTokenWithSecretSchema = ApiTokenSchema.merge(
|
||||
z.object({
|
||||
secret: z.string().describe('The secret part of the API token'),
|
||||
}),
|
||||
).describe(
|
||||
'This is returned once after an api token is created to let the user know what their token is.',
|
||||
)
|
||||
|
||||
export type ApiTokenWithSecretDto = z.infer<typeof ApiTokenWithSecretSchema>
|
28
commons/src/dtos/api-token/api-token.dto.ts
Normal file
28
commons/src/dtos/api-token/api-token.dto.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const ApiTokenSchema = z
|
||||
.object({
|
||||
label: z.string().describe('The label of the token'),
|
||||
keyId: z.string().describe('The id of the token'),
|
||||
createdAt: z.string().datetime().describe('When this token was created'),
|
||||
validUntil: z
|
||||
.string()
|
||||
.datetime()
|
||||
.describe('How long this token is valid fro'),
|
||||
lastUsedAt: z
|
||||
.string()
|
||||
.datetime()
|
||||
.nullable()
|
||||
.describe('When this token was last used'),
|
||||
})
|
||||
.describe(
|
||||
'Represents an access token for the public API. Each API token is bound to a user account. A user can have multiple API tokens.',
|
||||
)
|
||||
|
||||
export type ApiTokenDto = z.infer<typeof ApiTokenSchema>
|
9
commons/src/dtos/api-token/index.ts
Normal file
9
commons/src/dtos/api-token/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './api-token.dto.js'
|
||||
export * from './api-token-create.dto.js'
|
||||
export * from './api-token-with-secret.dto.js'
|
16
commons/src/dtos/auth/index.ts
Normal file
16
commons/src/dtos/auth/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './ldap-login.dto.js'
|
||||
export * from './ldap-login-response.dto.js'
|
||||
export * from './login.dto.js'
|
||||
export * from './logout-response.dto.js'
|
||||
export * from './pending-user-confirmation.dto.js'
|
||||
export * from './provider-type.enum.js'
|
||||
export * from './register.dto.js'
|
||||
export * from './update-password.dto.js'
|
||||
export * from './username-check.dto.js'
|
||||
export * from './username-check-reponse.dto.js'
|
15
commons/src/dtos/auth/ldap-login-response.dto.ts
Normal file
15
commons/src/dtos/auth/ldap-login-response.dto.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const LdapLoginResponseSchema = z
|
||||
.object({
|
||||
newUser: z.boolean().describe('If the LDAP user was newly created.'),
|
||||
})
|
||||
.describe('DTO to login via a LDAP server.')
|
||||
|
||||
export type LdapLoginResponseDto = z.infer<typeof LdapLoginResponseSchema>
|
16
commons/src/dtos/auth/ldap-login.dto.ts
Normal file
16
commons/src/dtos/auth/ldap-login.dto.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const LdapLoginSchema = z
|
||||
.object({
|
||||
username: z.string().describe('The username to log in at the LDAP server'),
|
||||
password: z.string().describe('The password to log in at the LDAP server'),
|
||||
})
|
||||
.describe('DTO to login via a LDAP server.')
|
||||
|
||||
export type LdapLoginDto = z.infer<typeof LdapLoginSchema>
|
20
commons/src/dtos/auth/login.dto.ts
Normal file
20
commons/src/dtos/auth/login.dto.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const LoginSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.toLowerCase()
|
||||
.describe('The username to log in with local authentication'),
|
||||
password: z
|
||||
.string()
|
||||
.describe('The password to log in with local authentication'),
|
||||
})
|
||||
.describe('DTO for the login form of local accounts')
|
||||
|
||||
export type LoginDto = z.infer<typeof LoginSchema>
|
18
commons/src/dtos/auth/logout-response.dto.ts
Normal file
18
commons/src/dtos/auth/logout-response.dto.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const LogoutResponseSchema = z
|
||||
.object({
|
||||
redirect: z
|
||||
.string()
|
||||
.url()
|
||||
.describe('Where the user shall be redirected to after the logout.'),
|
||||
})
|
||||
.describe('Information the user gets after logging out.')
|
||||
|
||||
export type LogoutResponseDto = z.infer<typeof LogoutResponseSchema>
|
34
commons/src/dtos/auth/pending-user-confirmation.dto.ts
Normal file
34
commons/src/dtos/auth/pending-user-confirmation.dto.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const PendingUserConfirmationSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(64)
|
||||
.toLowerCase()
|
||||
.describe('The chosen new username for the pending user'),
|
||||
displayName: z
|
||||
.string()
|
||||
.describe('The new display name for the pending user'),
|
||||
profilePicture: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe(
|
||||
'The URL to the chosen profile picture or null to use the auto-generated one',
|
||||
),
|
||||
})
|
||||
.describe(
|
||||
'DTO for the confirmation of a new user account. When a new user is created through OIDC login, they get asked to choose some details for their new account.',
|
||||
)
|
||||
|
||||
export type PendingUserConfirmationDto = z.infer<
|
||||
typeof PendingUserConfirmationSchema
|
||||
>
|
12
commons/src/dtos/auth/provider-type.enum.ts
Normal file
12
commons/src/dtos/auth/provider-type.enum.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export enum ProviderType {
|
||||
GUEST = 'guest',
|
||||
LOCAL = 'local',
|
||||
LDAP = 'ldap',
|
||||
OIDC = 'oidc',
|
||||
}
|
24
commons/src/dtos/auth/register.dto.ts
Normal file
24
commons/src/dtos/auth/register.dto.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const RegisterSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(64)
|
||||
.toLowerCase()
|
||||
.describe('The new username for local account registration'),
|
||||
displayName: z.string().describe('The display name of the new user'),
|
||||
password: z
|
||||
.string()
|
||||
.min(6)
|
||||
.describe('The new password for the local account'),
|
||||
})
|
||||
.describe('DTO to register a local user account')
|
||||
|
||||
export type RegisterDto = z.infer<typeof RegisterSchema>
|
18
commons/src/dtos/auth/update-password.dto.ts
Normal file
18
commons/src/dtos/auth/update-password.dto.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const UpdatePasswordSchema = z
|
||||
.object({
|
||||
currentPassword: z
|
||||
.string()
|
||||
.min(6)
|
||||
.describe('The current password of the user'),
|
||||
newPassword: z.string().min(6).describe('The new password of the user'),
|
||||
})
|
||||
.describe('DTO to update the password of a local user account')
|
||||
|
||||
export type UpdatePasswordDto = z.infer<typeof UpdatePasswordSchema>
|
18
commons/src/dtos/auth/username-check-reponse.dto.ts
Normal file
18
commons/src/dtos/auth/username-check-reponse.dto.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const UsernameCheckResponseSchema = z
|
||||
.object({
|
||||
usernameAvailable: z
|
||||
.boolean()
|
||||
.describe('Whether the chosen username is available or not'),
|
||||
})
|
||||
.describe('Response to the username check on the register forms')
|
||||
|
||||
export type UsernameCheckResponseDto = z.infer<
|
||||
typeof UsernameCheckResponseSchema
|
||||
>
|
17
commons/src/dtos/auth/username-check.dto.ts
Normal file
17
commons/src/dtos/auth/username-check.dto.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const UsernameCheckSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.toLowerCase()
|
||||
.describe("The username the user want's to register"),
|
||||
})
|
||||
.describe('DTO to check if a username is available')
|
||||
|
||||
export type UsernameCheckDto = z.infer<typeof UsernameCheckSchema>
|
28
commons/src/dtos/edit/edit.dto.ts
Normal file
28
commons/src/dtos/edit/edit.dto.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const EditSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The username who changed this section of the note'),
|
||||
startPosition: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('The offset where the change starts in the note'),
|
||||
endPosition: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('The offset where the change ends in the note'),
|
||||
createdAt: z.string().datetime().describe('When this edit happened'),
|
||||
updatedAt: z.string().datetime().describe('When this edit was updated?'),
|
||||
})
|
||||
.describe('A edit in a note by username from startPosition to endPosition.')
|
||||
|
||||
export type EditDto = z.infer<typeof EditSchema>
|
7
commons/src/dtos/edit/index.ts
Normal file
7
commons/src/dtos/edit/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './edit.dto.js'
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { ProviderType } from '../auth/index.js'
|
||||
|
||||
export const AuthProviderWithCustomNameSchema = z
|
||||
.object({
|
||||
type: z
|
||||
.literal(ProviderType.LDAP)
|
||||
.or(z.literal(ProviderType.OIDC))
|
||||
.describe('The type of the auth provider'),
|
||||
identifier: z
|
||||
.string()
|
||||
.describe('The identifier with which the auth provider can be called'),
|
||||
providerName: z.string().describe('The name given to the auth provider'),
|
||||
theme: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The theme to apply for the login button.'),
|
||||
})
|
||||
.describe(
|
||||
'The configuration for an auth provider with a custom name. So you can have multiple of the same kind.',
|
||||
)
|
||||
|
||||
export type AuthProviderWithCustomNameDto = z.infer<
|
||||
typeof AuthProviderWithCustomNameSchema
|
||||
>
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
import { ProviderType } from '../auth/index.js'
|
||||
|
||||
export const AuthProviderWithoutCustomNameSchema = z
|
||||
.object({
|
||||
type: z
|
||||
.literal(ProviderType.LOCAL)
|
||||
.describe('The type of the auth provider'),
|
||||
})
|
||||
.describe('Represents the local authentication provider')
|
||||
|
||||
export type AuthProviderWithoutCustomNameDto = z.infer<
|
||||
typeof AuthProviderWithoutCustomNameSchema
|
||||
>
|
18
commons/src/dtos/frontend-config/auth-provider.dto.ts
Normal file
18
commons/src/dtos/frontend-config/auth-provider.dto.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { AuthProviderWithCustomNameSchema } from './auth-provider-with-custom-name.dto.js'
|
||||
import { AuthProviderWithoutCustomNameSchema } from './auth-provider-without-custom-name.dto.js'
|
||||
import { z } from 'zod'
|
||||
|
||||
export const AuthProviderSchema = z
|
||||
.union([
|
||||
AuthProviderWithoutCustomNameSchema,
|
||||
AuthProviderWithCustomNameSchema,
|
||||
])
|
||||
.describe('A general type for all auth providers')
|
||||
|
||||
export type AuthProviderDto = z.infer<typeof AuthProviderSchema>
|
23
commons/src/dtos/frontend-config/branding.dto.ts
Normal file
23
commons/src/dtos/frontend-config/branding.dto.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const BrandingSchema = z
|
||||
.object({
|
||||
name: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The name to be displayed next to the HedgeDoc logo'),
|
||||
logo: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('URL to the logo to be displayed next to the HedgeDoc logo'),
|
||||
})
|
||||
.describe('The configuration for branding of the HedgeDoc instance.')
|
||||
|
||||
export type BrandingDto = z.infer<typeof BrandingSchema>
|
53
commons/src/dtos/frontend-config/frontend-config.dto.ts
Normal file
53
commons/src/dtos/frontend-config/frontend-config.dto.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { GuestAccess } from '../permissions/index.js'
|
||||
import { ServerVersionSchema } from '../monitoring/index.js'
|
||||
import { BrandingSchema } from './branding.dto.js'
|
||||
import { SpecialUrlSchema } from './special-urls.dto.js'
|
||||
import { AuthProviderSchema } from './auth-provider.dto.js'
|
||||
|
||||
export const FrontendConfigSchema = z
|
||||
.object({
|
||||
guestAccess: z
|
||||
.nativeEnum(GuestAccess)
|
||||
.describe('Maximum access level for guest users'),
|
||||
allowRegister: z
|
||||
.boolean()
|
||||
.describe('Are users allowed to register on this instance?'),
|
||||
allowProfileEdits: z
|
||||
.boolean()
|
||||
.describe('Are users allowed to edit their profile information?'),
|
||||
allowChooseUsername: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Are users allowed to choose their username when signing up via OIDC?',
|
||||
),
|
||||
authProviders: z
|
||||
.array(AuthProviderSchema)
|
||||
.describe(
|
||||
'Which auth providers are enabled and how are they configured?',
|
||||
),
|
||||
branding: BrandingSchema.describe('Individual branding information'),
|
||||
useImageProxy: z.boolean().describe('Is an image proxy enabled?'),
|
||||
specialUrls: SpecialUrlSchema.describe('Links to some special pages'),
|
||||
version: ServerVersionSchema.describe('The version of HedgeDoc'),
|
||||
plantUmlServer: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('The PlantUML server that should be used to render.'),
|
||||
maxDocumentLength: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('The maximal length of each document'),
|
||||
})
|
||||
.describe(
|
||||
'Config properties that are received by the frontend to adjust its own behaviour',
|
||||
)
|
||||
|
||||
export type FrontendConfigDto = z.infer<typeof FrontendConfigSchema>
|
11
commons/src/dtos/frontend-config/index.ts
Normal file
11
commons/src/dtos/frontend-config/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './auth-provider.dto.js'
|
||||
export * from './auth-provider-with-custom-name.dto.js'
|
||||
export * from './auth-provider-without-custom-name.dto.js'
|
||||
export * from './branding.dto.js'
|
||||
export * from './frontend-config.dto.js'
|
||||
export * from './special-urls.dto.js'
|
28
commons/src/dtos/frontend-config/special-urls.dto.ts
Normal file
28
commons/src/dtos/frontend-config/special-urls.dto.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const SpecialUrlSchema = z
|
||||
.object({
|
||||
privacy: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('A link to the privacy notice'),
|
||||
termsOfUse: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('A link to the privacy notice'),
|
||||
imprint: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('A link to the imprint notice'),
|
||||
})
|
||||
.describe('The special urls an HedgeDoc instance can link to.')
|
||||
|
||||
export type SpecialUrlDto = z.infer<typeof SpecialUrlSchema>
|
20
commons/src/dtos/group/group-info.dto.ts
Normal file
20
commons/src/dtos/group/group-info.dto.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const GroupInfoSchema = z
|
||||
.object({
|
||||
name: z.string().describe('Name of the group'),
|
||||
displayName: z
|
||||
.string()
|
||||
.describe(
|
||||
'Display name of this group. This is used in the UI, when the group is mentioned.',
|
||||
),
|
||||
special: z.boolean().describe('Is this group special?'),
|
||||
})
|
||||
.describe('DTO that contains the information about a group.')
|
||||
|
||||
export type GroupInfoDto = z.infer<typeof GroupInfoSchema>
|
7
commons/src/dtos/group/index.ts
Normal file
7
commons/src/dtos/group/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './group-info.dto.js'
|
||||
export * from './special-group.enum.js'
|
10
commons/src/dtos/group/special-group.enum.ts
Normal file
10
commons/src/dtos/group/special-group.enum.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export enum SpecialGroup {
|
||||
EVERYONE = '_EVERYONE',
|
||||
LOGGED_IN = '_LOGGED_IN',
|
||||
}
|
17
commons/src/dtos/index.ts
Normal file
17
commons/src/dtos/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './alias/index.js'
|
||||
export * from './api-token/index.js'
|
||||
export * from './auth/index.js'
|
||||
export * from './edit/index.js'
|
||||
export * from './frontend-config/index.js'
|
||||
export * from './group/index.js'
|
||||
export * from './media/index.js'
|
||||
export * from './monitoring/index.js'
|
||||
export * from './note/index.js'
|
||||
export * from './permissions/index.js'
|
||||
export * from './revision/index.js'
|
||||
export * from './user/index.js'
|
6
commons/src/dtos/media/index.ts
Normal file
6
commons/src/dtos/media/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './media-upload.dto.js'
|
28
commons/src/dtos/media/media-upload.dto.ts
Normal file
28
commons/src/dtos/media/media-upload.dto.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const MediaUploadSchema = z
|
||||
.object({
|
||||
uuid: z.string().uuid().describe('The uuid of the media file'),
|
||||
fileName: z.string().describe('The original filename of the media upload'),
|
||||
noteId: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The note id to which the uploaded file is linked to'),
|
||||
createdAt: z
|
||||
.string()
|
||||
.datetime()
|
||||
.describe('The dater when the upload was created'),
|
||||
username: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The username which uploaded the file'),
|
||||
})
|
||||
.describe('Metadata for an uploaded file')
|
||||
|
||||
export type MediaUploadDto = z.infer<typeof MediaUploadSchema>
|
7
commons/src/dtos/monitoring/index.ts
Normal file
7
commons/src/dtos/monitoring/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './server-status.dto.js'
|
||||
export * from './server-version.dto.js'
|
62
commons/src/dtos/monitoring/server-status.dto.ts
Normal file
62
commons/src/dtos/monitoring/server-status.dto.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { ServerVersionSchema } from './server-version.dto.js'
|
||||
|
||||
export const ServerStatusSchema = z
|
||||
.object({
|
||||
serverVersion: ServerVersionSchema,
|
||||
onlineNotes: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of notes that are currently being worked on'),
|
||||
onlineUsers: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of user that are currently working on notes'),
|
||||
distinctOnlineUsers: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe(
|
||||
'Number of user that are currently working on notes. Each user only counts only once.',
|
||||
),
|
||||
notesCount: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of notes on the instance'),
|
||||
registeredUsers: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of user that are currently registered'),
|
||||
onlineRegisteredUsers: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of user that are currently registered and online'),
|
||||
distinctOnlineRegisteredUsers: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe(
|
||||
'Number of user that are currently registered and online. Each user only counts only once.',
|
||||
),
|
||||
isConnectionBusy: z
|
||||
.boolean()
|
||||
.describe('If the connection is currently busy'),
|
||||
connectionSocketQueueLength: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of connections in the queue'),
|
||||
isDisconnectBusy: z
|
||||
.boolean()
|
||||
.describe('If the connection is currently busy'),
|
||||
disconnectSocketQueueLength: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of disconnections in the queue'),
|
||||
})
|
||||
.describe('The server status of the HedgeDoc instance.')
|
||||
|
||||
export type ServerStatusDto = z.infer<typeof ServerStatusSchema>
|
22
commons/src/dtos/monitoring/server-version.dto.ts
Normal file
22
commons/src/dtos/monitoring/server-version.dto.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const ServerVersionSchema = z
|
||||
.object({
|
||||
major: z.number().positive().describe('The major version of the server'),
|
||||
minor: z.number().positive().describe('The minor version of the server'),
|
||||
patch: z.number().positive().describe('The patch version of the server'),
|
||||
preRelease: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The pre release text of the server'),
|
||||
commit: z.string().optional().describe('The commit of the server'),
|
||||
fullString: z.string().describe('The full version string of the server'),
|
||||
})
|
||||
.describe('The version of the HedgeDoc server.')
|
||||
|
||||
export type ServerVersionDto = z.infer<typeof ServerVersionSchema>
|
9
commons/src/dtos/note/index.ts
Normal file
9
commons/src/dtos/note/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './note.dto.js'
|
||||
export * from './note.media-deletion.dto.js'
|
||||
export * from './note-metadata.dto.js'
|
||||
export * from './note-metadata-update.dto.js'
|
24
commons/src/dtos/note/note-metadata-update.dto.ts
Normal file
24
commons/src/dtos/note/note-metadata-update.dto.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteMetadataUpdateSchema = z
|
||||
.object({
|
||||
title: z
|
||||
.string()
|
||||
.describe(
|
||||
'The new title of the note. Can not contain any markup and might be empty',
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.describe(
|
||||
'The new description of the note. Can not contain any markup but might be empty.',
|
||||
),
|
||||
tags: z.array(z.string()).describe('The new tags for this note.'),
|
||||
})
|
||||
.describe('DTO for updating the note metadata')
|
||||
|
||||
export type NoteMetadataUpdate = z.infer<typeof NoteMetadataUpdateSchema>
|
56
commons/src/dtos/note/note-metadata.dto.ts
Normal file
56
commons/src/dtos/note/note-metadata.dto.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { AliasSchema } from '../alias/index.js'
|
||||
import { NotePermissionsSchema } from '../permissions/index.js'
|
||||
|
||||
export const NoteMetadataSchema = z
|
||||
.object({
|
||||
id: z.string().describe('The id of the note'),
|
||||
aliases: z.array(AliasSchema).describe('All aliases of the note'),
|
||||
primaryAddress: z
|
||||
.string()
|
||||
.describe(
|
||||
'The primary address/alias of the note. If at least one alias is set, this is the primary alias.',
|
||||
),
|
||||
title: z
|
||||
.string()
|
||||
.describe(
|
||||
'The title of the note. Does not contain any markup but might be empty.',
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.describe(
|
||||
'The description of the note. Does not contain any markup but might be empty.',
|
||||
),
|
||||
tags: z.array(z.string()).describe('List of tags assigned to this note'),
|
||||
version: z
|
||||
.number()
|
||||
.describe('The HedgeDoc version this note was created in'),
|
||||
updatedAt: z
|
||||
.string()
|
||||
.datetime()
|
||||
.describe('The timestamp when the note was last updated'),
|
||||
updateUsername: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The user that last updated the note'),
|
||||
viewCount: z
|
||||
.number()
|
||||
.describe('Counts how many times the note has been viewed'),
|
||||
createdAt: z
|
||||
.string()
|
||||
.datetime()
|
||||
.describe('Timestamp when the note was created'),
|
||||
editedBy: z.array(z.string()).describe('List of users who edited the note'),
|
||||
permissions: NotePermissionsSchema.describe(
|
||||
'The permissions of the current note',
|
||||
),
|
||||
})
|
||||
.describe('The metadata of a note')
|
||||
|
||||
export type NoteMetadataDto = z.infer<typeof NoteMetadataSchema>
|
19
commons/src/dtos/note/note.dto.ts
Normal file
19
commons/src/dtos/note/note.dto.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { EditSchema } from '../edit/edit.dto.js'
|
||||
import { NoteMetadataSchema } from './note-metadata.dto.js'
|
||||
|
||||
export const NoteSchema = z
|
||||
.object({
|
||||
content: z.string().describe('The markdown content of the note'),
|
||||
metadata: NoteMetadataSchema,
|
||||
editedByAtPosition: z.array(EditSchema).describe('The edit information '),
|
||||
})
|
||||
.describe('DTO representing a note')
|
||||
|
||||
export type NoteDto = z.infer<typeof NoteSchema>
|
21
commons/src/dtos/note/note.media-deletion.dto.ts
Normal file
21
commons/src/dtos/note/note.media-deletion.dto.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteMediaDeletionSchema = z
|
||||
.object({
|
||||
keepMedia: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Indicates whether existing media uploads for the note should be kept',
|
||||
),
|
||||
})
|
||||
.describe(
|
||||
'DTO for deleting a note with the option to remove associated uploads as well',
|
||||
)
|
||||
|
||||
export type NoteMediaDeletionDto = z.infer<typeof NoteMediaDeletionSchema>
|
15
commons/src/dtos/permissions/change-note-owner.dto.ts
Normal file
15
commons/src/dtos/permissions/change-note-owner.dto.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const ChangeNoteOwnerSchema = z
|
||||
.object({
|
||||
owner: z.string().describe('The username of the new owner.'),
|
||||
})
|
||||
.describe('DTO to change the owner of a note.')
|
||||
|
||||
export type ChangeNoteOwnerDto = z.infer<typeof ChangeNoteOwnerSchema>
|
27
commons/src/dtos/permissions/guest-access.enum.ts
Normal file
27
commons/src/dtos/permissions/guest-access.enum.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export enum GuestAccess {
|
||||
DENY = 'deny',
|
||||
READ = 'read',
|
||||
WRITE = 'write',
|
||||
CREATE = 'create',
|
||||
}
|
||||
|
||||
export const getGuestAccessOrdinal = (guestAccess: GuestAccess): number => {
|
||||
switch (guestAccess) {
|
||||
case GuestAccess.DENY:
|
||||
return 0
|
||||
case GuestAccess.READ:
|
||||
return 1
|
||||
case GuestAccess.WRITE:
|
||||
return 2
|
||||
case GuestAccess.CREATE:
|
||||
return 3
|
||||
default:
|
||||
throw Error('Unknown permission')
|
||||
}
|
||||
}
|
14
commons/src/dtos/permissions/index.ts
Normal file
14
commons/src/dtos/permissions/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './change-note-owner.dto.js'
|
||||
export * from './guest-access.enum.js'
|
||||
export * from './note-group-permission-entry.dto.js'
|
||||
export * from './note-group-permission-update.dto.js'
|
||||
export * from './note-permissions-update.dto.js'
|
||||
export * from './note-permissions.dto.js'
|
||||
export * from './note-user-permission-entry.dto.js'
|
||||
export * from './note-user-permission-update.dto.js'
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteGroupPermissionEntrySchema = z
|
||||
.object({
|
||||
groupName: z.string().describe('The name of the group'),
|
||||
canEdit: z.boolean().describe('If the group can edit or only read'),
|
||||
})
|
||||
.describe('DTO for the permission a group has.')
|
||||
|
||||
export type NoteGroupPermissionEntryDto = z.infer<
|
||||
typeof NoteGroupPermissionEntrySchema
|
||||
>
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteGroupPermissionUpdateSchema = z
|
||||
.object({
|
||||
groupName: z.string().describe('The name of the group'),
|
||||
canEdit: z.boolean().describe('If the group can edit or only read'),
|
||||
})
|
||||
.describe('DTO to update the permission of a group.')
|
||||
|
||||
export type NoteGroupPermissionUpdateDto = z.infer<
|
||||
typeof NoteGroupPermissionUpdateSchema
|
||||
>
|
23
commons/src/dtos/permissions/note-permissions-update.dto.ts
Normal file
23
commons/src/dtos/permissions/note-permissions-update.dto.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
import { NoteUserPermissionUpdateSchema } from './note-user-permission-update.dto.js'
|
||||
import { NoteGroupPermissionUpdateSchema } from './note-group-permission-update.dto.js'
|
||||
|
||||
export const NotePermissionsUpdateSchema = z
|
||||
.object({
|
||||
sharedToUsers: z
|
||||
.array(NoteUserPermissionUpdateSchema)
|
||||
.describe('List of users the note is shared with'),
|
||||
sharedToGroups: z
|
||||
.array(NoteGroupPermissionUpdateSchema)
|
||||
.describe('List of groups that the note is shared with'),
|
||||
})
|
||||
.describe('DTO to update the permissions of a note.')
|
||||
|
||||
export type NotePermissionsUpdateDto = z.infer<
|
||||
typeof NotePermissionsUpdateSchema
|
||||
>
|
23
commons/src/dtos/permissions/note-permissions.dto.ts
Normal file
23
commons/src/dtos/permissions/note-permissions.dto.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { NoteUserPermissionEntrySchema } from './note-user-permission-entry.dto.js'
|
||||
import { NoteGroupPermissionEntrySchema } from './note-group-permission-entry.dto.js'
|
||||
|
||||
export const NotePermissionsSchema = z
|
||||
.object({
|
||||
owner: z.string().nullable().describe('Username of the owner of the note'),
|
||||
sharedToUsers: z
|
||||
.array(NoteUserPermissionEntrySchema)
|
||||
.describe('List of users the note is shared with'),
|
||||
sharedToGroups: z
|
||||
.array(NoteGroupPermissionEntrySchema)
|
||||
.describe('List of groups that the note is shared with'),
|
||||
})
|
||||
.describe('Represents the permissions of a note')
|
||||
|
||||
export type NotePermissionsDto = z.infer<typeof NotePermissionsSchema>
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteUserPermissionEntrySchema = z
|
||||
.object({
|
||||
username: z.string().describe('The name of the user'),
|
||||
canEdit: z.boolean().describe('If the group can edit or only read'),
|
||||
})
|
||||
.describe('DTO for the permission a group has.')
|
||||
|
||||
export type NoteUserPermissionEntryDto = z.infer<
|
||||
typeof NoteUserPermissionEntrySchema
|
||||
>
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const NoteUserPermissionUpdateSchema = z
|
||||
.object({
|
||||
username: z.string().toLowerCase().describe('The name of the user'),
|
||||
canEdit: z.boolean().describe('If the group can edit or only read'),
|
||||
})
|
||||
.describe('DTO to update the permission of a user.')
|
||||
|
||||
export type NoteUserPermissionUpdateDto = z.infer<
|
||||
typeof NoteUserPermissionUpdateSchema
|
||||
>
|
8
commons/src/dtos/revision/index.ts
Normal file
8
commons/src/dtos/revision/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './revision.dto.js'
|
||||
export * from './revision-metadata.dto.js'
|
41
commons/src/dtos/revision/revision-metadata.dto.ts
Normal file
41
commons/src/dtos/revision/revision-metadata.dto.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const RevisionMetadataSchema = z
|
||||
.object({
|
||||
id: z.number().describe('The id of the revision.'),
|
||||
createdAt: z.string().datetime().describe('When the revision was created.'),
|
||||
length: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('The length of the content of the revision.'),
|
||||
authorUsernames: z
|
||||
.array(z.string().toLowerCase())
|
||||
.describe(
|
||||
'A list of all usernames of the users that worked on the revision.',
|
||||
),
|
||||
anonymousAuthorCount: z
|
||||
.number()
|
||||
.positive()
|
||||
.describe('Number of anonymous users that worked on the revision.'),
|
||||
title: z
|
||||
.string()
|
||||
.describe(
|
||||
'The title of the revision. Does not contain any markup but might be empty.',
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.describe(
|
||||
'The description of the revision. Does not contain any markup but might be empty.',
|
||||
),
|
||||
tags: z
|
||||
.array(z.string())
|
||||
.describe('List of tags assigned to this revision'),
|
||||
})
|
||||
.describe('DTO that describes the metadata of a revision.')
|
||||
|
||||
export type RevisionMetadataDto = z.infer<typeof RevisionMetadataSchema>
|
23
commons/src/dtos/revision/revision.dto.ts
Normal file
23
commons/src/dtos/revision/revision.dto.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { EditSchema } from '../edit/edit.dto.js'
|
||||
import { RevisionMetadataSchema } from './revision-metadata.dto.js'
|
||||
|
||||
export const RevisionSchema = RevisionMetadataSchema.merge(
|
||||
z.object({
|
||||
content: z.string().describe('The content of the revision'),
|
||||
patch: z.string().describe('The patch or diff to the previous revision'),
|
||||
edits: z
|
||||
.array(EditSchema)
|
||||
.describe('A list of users, who created this revision'),
|
||||
}),
|
||||
).describe(
|
||||
'A revision is the state of a note content at a specific time. This is used to go back to previous version of a note.',
|
||||
)
|
||||
|
||||
export type RevisionDto = z.infer<typeof RevisionSchema>
|
17
commons/src/dtos/user/full-user-info-with-id.dto.ts
Normal file
17
commons/src/dtos/user/full-user-info-with-id.dto.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
import { FullUserInfoSchema } from './full-user-info.dto.js'
|
||||
|
||||
export const FullUserInfoWithIdSchema = FullUserInfoSchema.merge(
|
||||
z.object({
|
||||
id: z.string().describe('The id from the LDAP server'),
|
||||
}),
|
||||
).describe(
|
||||
'The full user information with id is only used during the LDAP login process',
|
||||
)
|
||||
|
||||
export type FullUserInfoWithIdDto = z.infer<typeof FullUserInfoWithIdSchema>
|
21
commons/src/dtos/user/full-user-info.dto.ts
Normal file
21
commons/src/dtos/user/full-user-info.dto.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
import { UserInfoSchema } from './user-info.dto.js'
|
||||
|
||||
export const FullUserInfoSchema = UserInfoSchema.merge(
|
||||
z.object({
|
||||
email: z
|
||||
.string()
|
||||
.email()
|
||||
.nullable()
|
||||
.describe('The email address of the user if known'),
|
||||
}),
|
||||
).describe(
|
||||
'The full user information is only presented to the logged in user itself. For privacy reasons the email address is only here',
|
||||
)
|
||||
|
||||
export type FullUserInfoDto = z.infer<typeof FullUserInfoSchema>
|
10
commons/src/dtos/user/index.ts
Normal file
10
commons/src/dtos/user/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
export * from './full-user-info.dto.js'
|
||||
export * from './full-user-info-with-id.dto.js'
|
||||
export * from './login-user-info.dto.js'
|
||||
export * from './update-user-info.dto.js'
|
||||
export * from './user-info.dto.js'
|
21
commons/src/dtos/user/login-user-info.dto.ts
Normal file
21
commons/src/dtos/user/login-user-info.dto.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { ProviderType } from '../auth/index.js'
|
||||
import { FullUserInfoSchema } from './full-user-info.dto.js'
|
||||
|
||||
export const LoginUserInfoSchema = FullUserInfoSchema.merge(
|
||||
z.object({
|
||||
authProvider: z
|
||||
.nativeEnum(ProviderType)
|
||||
.describe('The type of login provider used for the current session'),
|
||||
}),
|
||||
).describe(
|
||||
'Information about the user and their auth method for the current session',
|
||||
)
|
||||
|
||||
export type LoginUserInfoDto = z.infer<typeof LoginUserInfoSchema>
|
19
commons/src/dtos/user/update-user-info.dto.ts
Normal file
19
commons/src/dtos/user/update-user-info.dto.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
|
||||
export const UpdateUserInfoSchema = z
|
||||
.object({
|
||||
displayName: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The new display name of the user.'),
|
||||
email: z.string().email().nullable().describe('The new email of the user.'),
|
||||
})
|
||||
.describe('The update of a user profile.')
|
||||
|
||||
export type UpdateUserInfoDto = z.infer<typeof UpdateUserInfoSchema>
|
20
commons/src/dtos/user/user-info.dto.ts
Normal file
20
commons/src/dtos/user/user-info.dto.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { z } from 'zod'
|
||||
|
||||
export const UserInfoSchema = z
|
||||
.object({
|
||||
username: z.string().describe("The user's username"),
|
||||
displayName: z.string().describe('The display name of the user'),
|
||||
photoUrl: z
|
||||
.string()
|
||||
.url()
|
||||
.nullable()
|
||||
.describe('The URL to the profile picture of the user'),
|
||||
})
|
||||
.describe('Represents the public information about a user')
|
||||
|
||||
export type UserInfoDto = z.infer<typeof UserInfoSchema>
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './dtos/index.js'
|
||||
export * from './frontmatter-extractor/index.js'
|
||||
export * from './message-transporters/index.js'
|
||||
export * from './note-frontmatter/index.js'
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export * from './permissions.js'
|
||||
export * from './permissions.types.js'
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { userCanEdit, userIsOwner } from './permissions.js'
|
||||
import { NotePermissions, SpecialGroup } from './permissions.types.js'
|
||||
import { describe, expect, it } from '@jest/globals'
|
||||
import { NotePermissionsDto, SpecialGroup } from '../dtos/index.js'
|
||||
|
||||
describe('Permissions', () => {
|
||||
const testPermissions: NotePermissions = {
|
||||
const testPermissions: NotePermissionsDto = {
|
||||
owner: 'owner',
|
||||
sharedToUsers: [
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { NotePermissions, SpecialGroup } from './permissions.types.js'
|
||||
import { NotePermissionsDto, SpecialGroup } from '../dtos/index.js'
|
||||
|
||||
/**
|
||||
* Checks if the given user is the owner of a note.
|
||||
|
@ -13,7 +13,7 @@ import { NotePermissions, SpecialGroup } from './permissions.types.js'
|
|||
* @return True if the user is the owner of the note
|
||||
*/
|
||||
export const userIsOwner = (
|
||||
permissions: NotePermissions,
|
||||
permissions: NotePermissionsDto,
|
||||
user?: string,
|
||||
): boolean => {
|
||||
return !!user && permissions.owner === user
|
||||
|
@ -27,7 +27,7 @@ export const userIsOwner = (
|
|||
* @return True if the user has the permission to edit the note
|
||||
*/
|
||||
export const userCanEdit = (
|
||||
permissions: NotePermissions,
|
||||
permissions: NotePermissionsDto,
|
||||
user?: string,
|
||||
): boolean => {
|
||||
const isOwner = userIsOwner(permissions, user)
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export interface NotePermissions {
|
||||
owner: string | null
|
||||
sharedToUsers: NoteUserPermissionEntry[]
|
||||
sharedToGroups: NoteGroupPermissionEntry[]
|
||||
}
|
||||
|
||||
export interface NoteUserPermissionEntry {
|
||||
username: string
|
||||
canEdit: boolean
|
||||
}
|
||||
|
||||
export interface NoteGroupPermissionEntry {
|
||||
groupName: string
|
||||
canEdit: boolean
|
||||
}
|
||||
export enum AccessLevel {
|
||||
NONE,
|
||||
READ_ONLY,
|
||||
WRITEABLE,
|
||||
}
|
||||
|
||||
export enum SpecialGroup {
|
||||
EVERYONE = '_EVERYONE',
|
||||
LOGGED_IN = '_LOGGED_IN',
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue