Skip to content

Commit 800582a

Browse files
committed
Merge branch 'self-hosting' into dev
2 parents e63eec9 + 0dcc349 commit 800582a

File tree

22 files changed

+869
-110
lines changed

22 files changed

+869
-110
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ dist
1414

1515
.DS_Store
1616

17-
deploy-*.sh
17+
deploy-*.sh
18+
19+
postgres_data
20+
keydb_data

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ DeepNotes is an open source, end-to-end encrypted infinite canvas note-taking ap
1313
- **Flexible note system:** Organize your notes in whatever way you want.
1414
- **Lifelong storage:** Never lose your notes ever again.
1515

16+
## Development
17+
18+
```console
19+
git clone https://github.com/DeepNotesApp/DeepNotes && cd DeepNotes && cp template.env .env && pnpm install && pnpm run repo:build && docker-compose up -d
20+
```
21+
22+
(On Windows, use WSL or Git Bash to run the commands above)
23+
24+
1. Run `pnpm run dev` to start the backend servers.
25+
2. Run one of these commands to start the frontend server:
26+
- `pnpm run dev:spa` to start the Single Page Application app.
27+
- `pnpm run dev:ssr` to start the Server Side Rendered app.
28+
- `pnpm run dev:electron` to start the Electron app.
29+
- `pnpm run dev:android` to start the Android app (requires Android Studio).
30+
- `pnpm run dev:ios` to start the iOS app (requires Xcode).
31+
1632
## Special thanks to these libraries for making DeepNotes possible:
1733

1834
- [Vue.js](https://vuejs.org/): Reactivity, component system, and more

apps/app-server/src/data/redis.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { createRedisInstance } from '@deeplib/data';
2-
import type { Cluster } from 'ioredis';
32
import { once } from 'lodash';
43

5-
export const getRedis = once((): Cluster => createRedisInstance());
6-
export const getSub = once((): Cluster => createRedisInstance());
4+
export const getRedis = once(() => createRedisInstance());
5+
export const getSub = once(() => createRedisInstance());

apps/app-server/src/env.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ declare namespace NodeJS {
33
DEV?: string;
44
STAGING?: string;
55

6+
SEND_EMAILS: string;
7+
68
HOST: string;
79

810
APP_SERVER_PORT: string;

apps/app-server/src/trpc/api/sessions/login.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { DataTransaction } from '@stdlib/data';
1010
import { allAsyncProps, w3cEmailRegex } from '@stdlib/misc';
1111
import { TRPCError } from '@trpc/server';
1212
import type { Cluster } from 'ioredis';
13+
import type { Redis } from 'ioredis';
1314
import sodium from 'libsodium-wrappers';
1415
import { once } from 'lodash';
1516
import { nanoid } from 'nanoid';
@@ -242,7 +243,7 @@ export async function login({
242243
}
243244

244245
async function _checkFailedLoginAttempts(input: {
245-
redis: Cluster;
246+
redis: Redis | Cluster;
246247

247248
ip: string;
248249
email: string;
@@ -289,7 +290,7 @@ async function _checkFailedLoginAttempts(input: {
289290
}
290291

291292
async function _incrementFailedLoginAttempts(input: {
292-
redis: Cluster;
293+
redis: Redis | Cluster;
293294

294295
email: string;
295296
ip: string;

apps/app-server/src/trpc/api/users/account/email-change/request.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,24 @@ export async function request({
7474

7575
// Send email
7676

77-
await sendMail({
78-
from: {
79-
name: 'DeepNotes',
80-
81-
},
82-
to: [input.newEmail],
83-
subject: 'Verify your email address',
84-
html: `
85-
Use the following code to verify your email address: <b>${emailVerificationCode}</b>.<br/>
86-
If you did not request this action, you can safely ignore this email.
87-
`,
88-
});
77+
if (process.env.SEND_EMAILS !== 'false') {
78+
await sendMail({
79+
from: {
80+
name: 'DeepNotes',
81+
82+
},
83+
to: [input.newEmail],
84+
subject: 'Verify your email address',
85+
html: `
86+
Use the following code to verify your email address: <b>${emailVerificationCode}</b>.<br/>
87+
If you did not request this action, you can safely ignore this email.
88+
`,
89+
});
90+
} else {
91+
return {
92+
emailVerificationCode,
93+
};
94+
}
8995
});
9096
},
9197
);

apps/app-server/src/trpc/api/users/account/register.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { derivePasswordValues } from 'src/utils/crypto';
1010
import { registerUser, userRegistrationSchema } from 'src/utils/users';
1111
import { z } from 'zod';
1212

13+
import { verifyEmail } from './verify-email';
14+
1315
const baseProcedure = publicProcedure.input(
1416
z
1517
.object({
@@ -28,7 +30,9 @@ export async function register({
2830
ctx,
2931
input,
3032
}: InferProcedureOpts<typeof baseProcedure>) {
31-
return await ctx.dataAbstraction.transaction(async (dtrx) => {
33+
let emailVerificationCode: string | null;
34+
35+
await ctx.dataAbstraction.transaction(async (dtrx) => {
3236
// Get user
3337

3438
let user = await UserModel.query()
@@ -79,11 +83,24 @@ export async function register({
7983

8084
// Send email
8185

82-
await sendRegistrationEmail({
83-
email: input.email,
84-
emailVerificationCode: user.email_verification_code,
85-
});
86+
if (process.env.SEND_EMAILS !== 'false') {
87+
await sendRegistrationEmail({
88+
email: input.email,
89+
emailVerificationCode: user.email_verification_code,
90+
});
91+
}
92+
93+
emailVerificationCode = user.email_verification_code;
8694
});
95+
96+
if (process.env.SEND_EMAILS === 'false') {
97+
await verifyEmail({
98+
ctx,
99+
input: {
100+
emailVerificationCode: emailVerificationCode!,
101+
},
102+
});
103+
}
87104
}
88105

89106
export async function sendRegistrationEmail(input: {

apps/app-server/src/websocket/users/account/email-change/finish.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ export async function changeEmailStep2({
202202
invalidateAllSessions(ctx.userId, { dtrx }),
203203
]);
204204

205-
await ctx.stripe.customers.update(user.customer_id!, {
206-
email: newEmail,
207-
});
205+
if (user.customer_id != null) {
206+
await ctx.stripe.customers.update(user.customer_id!, {
207+
email: newEmail,
208+
});
209+
}
208210
});
209211
}

apps/client/quasar.config.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ const dotenv = require('dotenv');
1717

1818
const env = Object.assign(
1919
{},
20-
require('dotenv-expand').expand(
21-
dotenv.config({ path: '../../.env' }).parsed?.DEV
20+
require('dotenv-expand').expand({
21+
...dotenv.config({ path: '../../.env' }),
22+
23+
...(dotenv.config({ path: '../../.env' }).parsed?.DEV
2224
? dotenv.config({ path: '../../.env' }).parsed?.PRODEV
2325
? dotenv.config({ path: '../../.env.prodev' })
2426
: dotenv.config({ path: '../../.env.dev' })
25-
: dotenv.config({ path: '../../.env.prod' }),
26-
).parsed,
27+
: dotenv.config({ path: '../../.env.prod' })),
28+
}).parsed,
2729
objFromEntries(
2830
Object.entries(process.env ?? {}).filter(([key]) => /^\w+$/.test(key)),
2931
),

apps/client/src/env.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ declare namespace NodeJS {
1515

1616
STAGING?: string;
1717

18+
SEND_EMAILS: string;
19+
1820
HOST: string;
1921

2022
APP_SERVER_PORT: string;

0 commit comments

Comments
 (0)