2025-03-24 15:25:29 +11:00
|
|
|
import { TeamMemberRole } from '@prisma/client';
|
2024-02-06 16:16:10 +11:00
|
|
|
import { z } from 'zod';
|
|
|
|
|
|
|
|
|
|
import { PROTECTED_TEAM_URLS } from '@documenso/lib/constants/teams';
|
2024-12-11 19:39:50 +09:00
|
|
|
import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
|
2024-02-06 16:16:10 +11:00
|
|
|
|
2024-06-06 14:46:48 +10:00
|
|
|
import { ZUpdatePublicProfileMutationSchema } from '../profile-router/schema';
|
|
|
|
|
|
2024-02-06 16:16:10 +11:00
|
|
|
/**
|
|
|
|
|
* Restrict team URLs schema.
|
|
|
|
|
*
|
|
|
|
|
* Allowed characters:
|
|
|
|
|
* - Alphanumeric
|
|
|
|
|
* - Lowercase
|
|
|
|
|
* - Dashes
|
|
|
|
|
* - Underscores
|
|
|
|
|
*
|
|
|
|
|
* Conditions:
|
|
|
|
|
* - 3-30 characters
|
|
|
|
|
* - Cannot start and end with underscores or dashes.
|
|
|
|
|
* - Cannot contain consecutive underscores or dashes.
|
|
|
|
|
* - Cannot be a reserved URL in the PROTECTED_TEAM_URLS list
|
|
|
|
|
*/
|
|
|
|
|
export const ZTeamUrlSchema = z
|
|
|
|
|
.string()
|
|
|
|
|
.trim()
|
|
|
|
|
.min(3, { message: 'Team URL must be at least 3 characters long.' })
|
|
|
|
|
.max(30, { message: 'Team URL must not exceed 30 characters.' })
|
|
|
|
|
.toLowerCase()
|
|
|
|
|
.regex(/^[a-z0-9].*[^_-]$/, 'Team URL cannot start or end with dashes or underscores.')
|
|
|
|
|
.regex(/^(?!.*[-_]{2})/, 'Team URL cannot contain consecutive dashes or underscores.')
|
|
|
|
|
.regex(
|
|
|
|
|
/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/,
|
|
|
|
|
'Team URL can only contain letters, numbers, dashes and underscores.',
|
|
|
|
|
)
|
|
|
|
|
.refine((value) => !PROTECTED_TEAM_URLS.includes(value), {
|
|
|
|
|
message: 'This URL is already in use.',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZTeamNameSchema = z
|
|
|
|
|
.string()
|
|
|
|
|
.trim()
|
|
|
|
|
.min(3, { message: 'Team name must be at least 3 characters long.' })
|
|
|
|
|
.max(30, { message: 'Team name must not exceed 30 characters.' });
|
|
|
|
|
|
|
|
|
|
export const ZAcceptTeamInvitationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-25 04:27:19 +00:00
|
|
|
export const ZDeclineTeamInvitationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-06 16:16:10 +11:00
|
|
|
export const ZCreateTeamBillingPortalMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZCreateTeamMutationSchema = z.object({
|
|
|
|
|
teamName: ZTeamNameSchema,
|
|
|
|
|
teamUrl: ZTeamUrlSchema,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZCreateTeamEmailVerificationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
name: z.string().trim().min(1, { message: 'Please enter a valid name.' }),
|
|
|
|
|
email: z.string().trim().email().toLowerCase().min(1, 'Please enter a valid email.'),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZCreateTeamMemberInvitesMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
invitations: z.array(
|
|
|
|
|
z.object({
|
|
|
|
|
email: z.string().email().toLowerCase(),
|
|
|
|
|
role: z.nativeEnum(TeamMemberRole),
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZCreateTeamPendingCheckoutMutationSchema = z.object({
|
|
|
|
|
interval: z.union([z.literal('monthly'), z.literal('yearly')]),
|
|
|
|
|
pendingTeamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamEmailMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamEmailVerificationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamMembersMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
teamMemberIds: z.array(z.number()),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamMemberInvitationsMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
invitationIds: z.array(z.number()),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamPendingMutationSchema = z.object({
|
|
|
|
|
pendingTeamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZDeleteTeamTransferRequestMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZFindTeamInvoicesQuerySchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-12-11 19:39:50 +09:00
|
|
|
export const ZFindTeamMemberInvitesQuerySchema = ZFindSearchParamsSchema.extend({
|
2024-02-06 16:16:10 +11:00
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-12-11 19:39:50 +09:00
|
|
|
export const ZFindTeamMembersQuerySchema = ZFindSearchParamsSchema.extend({
|
2024-02-06 16:16:10 +11:00
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-12-11 19:39:50 +09:00
|
|
|
export const ZFindTeamsQuerySchema = ZFindSearchParamsSchema;
|
2024-02-06 16:16:10 +11:00
|
|
|
|
2024-12-11 19:39:50 +09:00
|
|
|
export const ZFindTeamsPendingQuerySchema = ZFindSearchParamsSchema;
|
2024-02-06 16:16:10 +11:00
|
|
|
|
|
|
|
|
export const ZGetTeamQuerySchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZGetTeamMembersQuerySchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZLeaveTeamMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZUpdateTeamMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
data: z.object({
|
|
|
|
|
name: ZTeamNameSchema,
|
|
|
|
|
url: ZTeamUrlSchema,
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZUpdateTeamEmailMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
data: z.object({
|
|
|
|
|
name: z.string().trim().min(1),
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZUpdateTeamMemberMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
teamMemberId: z.number(),
|
|
|
|
|
data: z.object({
|
|
|
|
|
role: z.nativeEnum(TeamMemberRole),
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
2024-06-06 14:46:48 +10:00
|
|
|
export const ZUpdateTeamPublicProfileMutationSchema = ZUpdatePublicProfileMutationSchema.pick({
|
|
|
|
|
bio: true,
|
|
|
|
|
enabled: true,
|
|
|
|
|
}).extend({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-06 16:16:10 +11:00
|
|
|
export const ZRequestTeamOwnerhsipTransferMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
newOwnerUserId: z.number(),
|
|
|
|
|
clearPaymentMethods: z.boolean(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZResendTeamEmailVerificationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const ZResendTeamMemberInvitationMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
invitationId: z.number(),
|
|
|
|
|
});
|
|
|
|
|
|
feat: add global settings for teams (#1391)
## Description
This PR introduces global settings for teams. At the moment, it allows
team admins to configure the following:
* The default visibility of the documents uploaded to the team account
* Whether to include the document owner (sender) details when sending
emails to the recipients.
### Include Sender Details
If the Sender Details setting is enabled, the emails sent by the team
will include the sender's name:
> "Example User" on behalf of "Example Team" has invited you to sign
"document.pdf"
Otherwise, the email will say:
> "Example Team" has invited you to sign "document.pdf"
### Default Document Visibility
This new option allows users to set the default visibility for the
documents uploaded to the team account. It can have the following
values:
* Everyone
* Manager and above
* Admins only
If the default document visibility isn't set, the document will be set
to the role of the user who created the document:
* If a user with the "User" role creates a document, the document's
visibility is set to "Everyone".
* Manager role -> "Manager and above"
* Admin role -> "Admins only"
Otherwise, if there is a default document visibility value, it uses that
value.
#### Gotcha
To avoid issues, the `document owner` and the `recipient` can access the
document irrespective of their role. For example:
* If a team member with the role "Member" uploads a document and the
default document visibility is "Admins", only the document owner and
admins can access the document.
* Similar to the other scenarios.
* If an admin uploads a document and the default document visibility is
"Admins", the recipient can access the document.
* The admins have access to all the documents.
* Managers have access to documents with the visibility set to
"Everyone" and "Manager and above"
* Members have access only to the documents with the visibility set to
"Everyone".
## Testing Performed
Tested it locally.
2024-11-08 13:50:49 +02:00
|
|
|
export const ZUpdateTeamBrandingSettingsMutationSchema = z.object({
|
|
|
|
|
teamId: z.number(),
|
|
|
|
|
settings: z.object({
|
|
|
|
|
brandingEnabled: z.boolean().optional().default(false),
|
|
|
|
|
brandingLogo: z.string().optional().default(''),
|
|
|
|
|
brandingUrl: z.string().optional().default(''),
|
|
|
|
|
brandingCompanyDetails: z.string().optional().default(''),
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-06 16:16:10 +11:00
|
|
|
export type TCreateTeamMutationSchema = z.infer<typeof ZCreateTeamMutationSchema>;
|
|
|
|
|
export type TCreateTeamEmailVerificationMutationSchema = z.infer<
|
|
|
|
|
typeof ZCreateTeamEmailVerificationMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TCreateTeamMemberInvitesMutationSchema = z.infer<
|
|
|
|
|
typeof ZCreateTeamMemberInvitesMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TCreateTeamPendingCheckoutMutationSchema = z.infer<
|
|
|
|
|
typeof ZCreateTeamPendingCheckoutMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TDeleteTeamEmailMutationSchema = z.infer<typeof ZDeleteTeamEmailMutationSchema>;
|
|
|
|
|
export type TDeleteTeamMembersMutationSchema = z.infer<typeof ZDeleteTeamMembersMutationSchema>;
|
|
|
|
|
export type TDeleteTeamMutationSchema = z.infer<typeof ZDeleteTeamMutationSchema>;
|
|
|
|
|
export type TDeleteTeamPendingMutationSchema = z.infer<typeof ZDeleteTeamPendingMutationSchema>;
|
|
|
|
|
export type TDeleteTeamTransferRequestMutationSchema = z.infer<
|
|
|
|
|
typeof ZDeleteTeamTransferRequestMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TFindTeamMemberInvitesQuerySchema = z.infer<typeof ZFindTeamMembersQuerySchema>;
|
|
|
|
|
export type TFindTeamMembersQuerySchema = z.infer<typeof ZFindTeamMembersQuerySchema>;
|
|
|
|
|
export type TFindTeamsQuerySchema = z.infer<typeof ZFindTeamsQuerySchema>;
|
|
|
|
|
export type TFindTeamsPendingQuerySchema = z.infer<typeof ZFindTeamsPendingQuerySchema>;
|
|
|
|
|
export type TGetTeamQuerySchema = z.infer<typeof ZGetTeamQuerySchema>;
|
|
|
|
|
export type TGetTeamMembersQuerySchema = z.infer<typeof ZGetTeamMembersQuerySchema>;
|
|
|
|
|
export type TLeaveTeamMutationSchema = z.infer<typeof ZLeaveTeamMutationSchema>;
|
|
|
|
|
export type TUpdateTeamMutationSchema = z.infer<typeof ZUpdateTeamMutationSchema>;
|
|
|
|
|
export type TUpdateTeamEmailMutationSchema = z.infer<typeof ZUpdateTeamEmailMutationSchema>;
|
|
|
|
|
export type TRequestTeamOwnerhsipTransferMutationSchema = z.infer<
|
|
|
|
|
typeof ZRequestTeamOwnerhsipTransferMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TResendTeamEmailVerificationMutationSchema = z.infer<
|
|
|
|
|
typeof ZResendTeamEmailVerificationMutationSchema
|
|
|
|
|
>;
|
|
|
|
|
export type TResendTeamMemberInvitationMutationSchema = z.infer<
|
|
|
|
|
typeof ZResendTeamMemberInvitationMutationSchema
|
|
|
|
|
>;
|
feat: add global settings for teams (#1391)
## Description
This PR introduces global settings for teams. At the moment, it allows
team admins to configure the following:
* The default visibility of the documents uploaded to the team account
* Whether to include the document owner (sender) details when sending
emails to the recipients.
### Include Sender Details
If the Sender Details setting is enabled, the emails sent by the team
will include the sender's name:
> "Example User" on behalf of "Example Team" has invited you to sign
"document.pdf"
Otherwise, the email will say:
> "Example Team" has invited you to sign "document.pdf"
### Default Document Visibility
This new option allows users to set the default visibility for the
documents uploaded to the team account. It can have the following
values:
* Everyone
* Manager and above
* Admins only
If the default document visibility isn't set, the document will be set
to the role of the user who created the document:
* If a user with the "User" role creates a document, the document's
visibility is set to "Everyone".
* Manager role -> "Manager and above"
* Admin role -> "Admins only"
Otherwise, if there is a default document visibility value, it uses that
value.
#### Gotcha
To avoid issues, the `document owner` and the `recipient` can access the
document irrespective of their role. For example:
* If a team member with the role "Member" uploads a document and the
default document visibility is "Admins", only the document owner and
admins can access the document.
* Similar to the other scenarios.
* If an admin uploads a document and the default document visibility is
"Admins", the recipient can access the document.
* The admins have access to all the documents.
* Managers have access to documents with the visibility set to
"Everyone" and "Manager and above"
* Members have access only to the documents with the visibility set to
"Everyone".
## Testing Performed
Tested it locally.
2024-11-08 13:50:49 +02:00
|
|
|
export type TUpdateTeamBrandingSettingsMutationSchema = z.infer<
|
|
|
|
|
typeof ZUpdateTeamBrandingSettingsMutationSchema
|
|
|
|
|
>;
|