mirror of
https://github.com/docmost/docmost.git
synced 2025-11-19 09:51:09 +10:00
implement new invitation system
* fix comments on the frontend * move jwt token service to its own module * other fixes and updates
This commit is contained in:
@ -9,9 +9,21 @@ export class EnvironmentService {
|
||||
return this.configService.get<string>('NODE_ENV');
|
||||
}
|
||||
|
||||
getAppUrl(): string {
|
||||
return (
|
||||
this.configService.get<string>('APP_URL') ||
|
||||
'http://localhost:' + this.getPort()
|
||||
);
|
||||
}
|
||||
|
||||
getPort(): number {
|
||||
return parseInt(this.configService.get<string>('PORT'));
|
||||
}
|
||||
|
||||
getAppSecret(): string {
|
||||
return this.configService.get<string>('APP_SECRET');
|
||||
}
|
||||
|
||||
getDatabaseURL(): string {
|
||||
return this.configService.get<string>('DATABASE_URL');
|
||||
}
|
||||
|
||||
@ -7,6 +7,9 @@ export class EnvironmentVariables {
|
||||
|
||||
@IsUrl({ protocols: ['postgres', 'postgresql'], require_tld: false })
|
||||
DATABASE_URL: string;
|
||||
|
||||
@IsString()
|
||||
APP_SECRET: string;
|
||||
}
|
||||
|
||||
export function validate(config: Record<string, any>) {
|
||||
@ -14,7 +17,13 @@ export function validate(config: Record<string, any>) {
|
||||
|
||||
const errors = validateSync(validatedConfig);
|
||||
if (errors.length > 0) {
|
||||
throw new Error(errors.toString());
|
||||
errors.map((error) => {
|
||||
console.error(error.toString());
|
||||
});
|
||||
console.log(
|
||||
'Please fix the environment variables and try again. Shutting down...',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
return validatedConfig;
|
||||
}
|
||||
|
||||
@ -18,8 +18,9 @@ export class MailService {
|
||||
|
||||
async sendEmail(message: MailMessage): Promise<void> {
|
||||
if (message.template) {
|
||||
// in case this method is used directly
|
||||
message.html = render(message.template);
|
||||
// in case this method is used directly. we do not send the tsx template from queue
|
||||
message.html = render(message.template, { pretty: true });
|
||||
message.text = render(message.template, { plainText: true });
|
||||
}
|
||||
|
||||
const sender = `${this.environmentService.getMailFromName()} <${this.environmentService.getMailFromAddress()}> `;
|
||||
@ -29,7 +30,10 @@ export class MailService {
|
||||
async sendToQueue(message: MailMessage): Promise<void> {
|
||||
if (message.template) {
|
||||
// transform the React object because it gets lost when sent via the queue
|
||||
message.html = render(message.template);
|
||||
message.html = render(message.template, { pretty: true });
|
||||
message.text = render(message.template, {
|
||||
plainText: true,
|
||||
});
|
||||
delete message.template;
|
||||
}
|
||||
await this.emailQueue.add(QueueJob.SEND_EMAIL, message);
|
||||
|
||||
@ -23,7 +23,7 @@ export const paragraph = {
|
||||
fontFamily:
|
||||
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
|
||||
color: '#333',
|
||||
lineHeight: 1.5,
|
||||
lineHeight: 1,
|
||||
fontSize: 14,
|
||||
};
|
||||
|
||||
@ -51,3 +51,16 @@ export const footer = {
|
||||
maxWidth: '580px',
|
||||
margin: '0 auto',
|
||||
};
|
||||
|
||||
export const button = {
|
||||
backgroundColor: '#176ae5',
|
||||
borderRadius: '3px',
|
||||
color: '#fff',
|
||||
fontFamily: "'Open Sans', 'Helvetica Neue', Arial",
|
||||
fontSize: '16px',
|
||||
textDecoration: 'none',
|
||||
textAlign: 'center' as const,
|
||||
display: 'block',
|
||||
width: '100px',
|
||||
padding: '8px',
|
||||
};
|
||||
|
||||
@ -3,11 +3,11 @@ import * as React from 'react';
|
||||
import { content, paragraph } from '../css/styles';
|
||||
import { MailBody } from '../partials/partials';
|
||||
|
||||
interface ChangePasswordEmailProps {
|
||||
interface Props {
|
||||
username?: string;
|
||||
}
|
||||
|
||||
export const ChangePasswordEmail = ({ username }: ChangePasswordEmailProps) => {
|
||||
export const ChangePasswordEmail = ({ username }: Props) => {
|
||||
return (
|
||||
<MailBody>
|
||||
<Section style={content}>
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
import { Section, Text } from '@react-email/components';
|
||||
import * as React from 'react';
|
||||
import { content, paragraph } from '../css/styles';
|
||||
import { MailBody } from '../partials/partials';
|
||||
|
||||
interface Props {
|
||||
invitedUserName: string;
|
||||
invitedUserEmail: string;
|
||||
}
|
||||
|
||||
export const InvitationAcceptedEmail = ({
|
||||
invitedUserName,
|
||||
invitedUserEmail,
|
||||
}: Props) => {
|
||||
return (
|
||||
<MailBody>
|
||||
<Section style={content}>
|
||||
<Text style={paragraph}>Hi there,</Text>
|
||||
<Text style={paragraph}>
|
||||
{invitedUserName} ({invitedUserEmail}) has accepted your invitation,
|
||||
and is now a member of the workspace.
|
||||
</Text>
|
||||
</Section>
|
||||
</MailBody>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvitationAcceptedEmail;
|
||||
@ -0,0 +1,37 @@
|
||||
import { Section, Text, Button } from '@react-email/components';
|
||||
import * as React from 'react';
|
||||
import { button, content, paragraph } from '../css/styles';
|
||||
import { MailBody } from '../partials/partials';
|
||||
|
||||
interface Props {
|
||||
inviteLink: string;
|
||||
}
|
||||
|
||||
export const InvitationEmail = ({ inviteLink }: Props) => {
|
||||
return (
|
||||
<MailBody>
|
||||
<Section style={content}>
|
||||
<Text style={paragraph}>Hi there,</Text>
|
||||
<Text style={paragraph}>You have been invited to Docmost.</Text>
|
||||
<Text style={paragraph}>
|
||||
Please click the button below to accept this invitation.
|
||||
</Text>
|
||||
</Section>
|
||||
<Section
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingLeft: '15px',
|
||||
paddingBottom: '15px',
|
||||
}}
|
||||
>
|
||||
<Button href={inviteLink} style={button}>
|
||||
Accept Invite
|
||||
</Button>
|
||||
</Section>
|
||||
</MailBody>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvitationEmail;
|
||||
@ -40,7 +40,7 @@ export function MailFooter() {
|
||||
<Section style={footer}>
|
||||
<Row>
|
||||
<Text style={{ textAlign: 'center', color: '#706a7b' }}>
|
||||
© {new Date().getFullYear()}, All Rights Reserved <br />
|
||||
© {new Date().getFullYear()} Docmost, All Rights Reserved <br />
|
||||
</Text>
|
||||
</Row>
|
||||
</Section>
|
||||
|
||||
Reference in New Issue
Block a user