+
+ Sign in to your account
+ Hi{firstName ? ' ' + firstName : ''}!
+
+ Click the link below to sign in to your account.
+
+
+
+ >
+ }
+ footer={
+
+ }
+ />
+ );
+}
diff --git a/server/src/email/templates/registration.tsx b/server/src/email/templates/registration.tsx
new file mode 100644
index 0000000..469bcad
--- /dev/null
+++ b/server/src/email/templates/registration.tsx
@@ -0,0 +1,52 @@
+import qs from 'qs';
+import { Button, Footer, Link, Prose, Title, Wrapper } from '../components';
+import { send } from '../resend';
+import { Senders } from '../senders';
+import { siteDomain } from '@@/util/dev';
+
+/** verify a user's email address for registration. */
+export async function emailRegistration(
+ emailAddress: string,
+ { token }: { token: string }
+) {
+ const url = `${siteDomain}/auth/activate?${qs.stringify({ token })}`;
+
+ return send(
+ {
+ to: emailAddress,
+ from: Senders.AUTH,
+ subject: SUBJECT,
+ react: Content({ url }),
+ },
+ { fallback: true }
+ );
+}
+
+const SUBJECT = 'Verify your email address';
+function Content({ url }: { url: string }) {
+ return (
+
+
+ Verify your email
+ Click the link below to finish creating your account.
+
+
+ >
+ }
+ footer={
+
+ }
+ />
+ );
+}
diff --git a/server/src/ics/cache.ts b/server/src/ics/cache.ts
index 350b299..6c0fcda 100644
--- a/server/src/ics/cache.ts
+++ b/server/src/ics/cache.ts
@@ -4,13 +4,8 @@ import { graph } from '@@/db/graph';
import { graphql } from '@@/db/lib/utilities';
import { WEBCAL_STALE_TIME } from '@@/CONSTANTS';
-import {
- Buckets,
- deleteS3File,
- getS3File,
- listS3Files,
- uploadS3File,
-} from '@@/s3/s3';
+import { s3 } from '@@/s3';
+import { Buckets } from '@@/s3/s3';
const BUCKET = Buckets.RESOURCE_BUCKET;
const PATH = 'ics/';
@@ -42,7 +37,7 @@ export async function getStaysMostRecent(after: number) {
}
export async function getCacheTimestamp() {
- const files = await listS3Files(BUCKET, PATH);
+ const files = await s3.listFiles(BUCKET, PATH);
if (!files?.data?.length) return null;
const recent = files.data
@@ -56,7 +51,7 @@ export async function getCacheTimestamp() {
}
export async function retrieveCache(ts: number) {
- const data = await getS3File({
+ const data = await s3.getFile({
bucket: BUCKET,
path: PATH + `${ts}.ics`,
});
@@ -73,7 +68,7 @@ export async function retrieveCache(ts: number) {
export async function updateCache(createdTS: number, newFile: string) {
const lastCache = await getCacheTimestamp();
- const success = await uploadS3File(
+ const success = await s3.uploadFile(
{
bucket: BUCKET,
path: PATH + `${createdTS}.ics`,
@@ -86,7 +81,7 @@ export async function updateCache(createdTS: number, newFile: string) {
}
if (lastCache) {
- deleteS3File({
+ s3.deleteFile({
bucket: BUCKET,
path: PATH + `${lastCache}.ics`,
}).catch(() => {});
diff --git a/server/src/s3/index.ts b/server/src/s3/index.ts
new file mode 100644
index 0000000..68f7a91
--- /dev/null
+++ b/server/src/s3/index.ts
@@ -0,0 +1,3 @@
+export * from './s3';
+export * as default from './s3';
+export * as s3 from './s3';
diff --git a/server/src/s3/s3.ts b/server/src/s3/s3.ts
index e8da0ce..47a89e9 100644
--- a/server/src/s3/s3.ts
+++ b/server/src/s3/s3.ts
@@ -35,7 +35,7 @@ type GetUploadUrlProps = {
// type:
expiresSec?: number;
};
-export async function getS3UploadUrl({
+export async function getUploadUrl({
bucket,
path,
expiresSec,
@@ -54,7 +54,7 @@ export async function getS3UploadUrl({
return { data: url };
}
-export async function uploadS3File(
+export async function uploadFile(
fp: FilePath,
options?: Partial
) {
@@ -74,22 +74,19 @@ export async function uploadS3File(
});
}
-export async function getSignedS3Url(
+export async function getSignedUrl(
uri: string,
expiresSec?: number
): Promise;
-export async function getSignedS3Url(
+export async function getSignedUrl(
filePath: FilePath,
expiresSec?: number
): Promise;
-export async function getSignedS3Url(
- p: string | FilePath,
- expiresSec?: number
-) {
+export async function getSignedUrl(p: string | FilePath, expiresSec?: number) {
let fp: FilePath;
if (typeof p === 'string') {
// parse S3 URI if needed
- const parsed = parseS3Uri(p);
+ const parsed = parseUri(p);
if (!parsed) return null;
fp = parsed;
} else fp = p;
@@ -111,7 +108,7 @@ function presignFile(fp: FilePath, expiresSec?: number) {
);
}
-export function parseS3Uri(uri: string) {
+export function parseUri(uri: string) {
const m = uri?.match(/^s3:\/\/([^\/]+)\/(.+)$/);
if (!m) return null;
return {
@@ -119,11 +116,11 @@ export function parseS3Uri(uri: string) {
path: m[2],
} as FilePath;
}
-export function getS3Uri(fp: FilePath) {
+export function getUri(fp: FilePath) {
return `s3://${fp.bucket}/${fp.path}`;
}
-export async function getS3File(fp: FilePath) {
+export async function getFile(fp: FilePath) {
try {
const { Body } = await s3.send(
new GetObjectCommand({
@@ -171,7 +168,7 @@ export async function doesFileExist(fp: FilePath) {
* delete a file
* @throws usually an {@link S3ServiceException}
*/
-export async function deleteS3File(fp: FilePath) {
+export async function deleteFile(fp: FilePath) {
await s3.send(
new DeleteObjectCommand({
Bucket: fp.bucket,
@@ -180,7 +177,7 @@ export async function deleteS3File(fp: FilePath) {
);
}
-export async function deleteS3Folder(fp: FilePath) {
+export async function deleteFolder(fp: FilePath) {
let deleted = 0; // number of files deleted
const errors: { key: string; code: string }[] = [];
@@ -223,7 +220,7 @@ export async function deleteS3Folder(fp: FilePath) {
return { deleted, errors };
}
-export async function listS3Files(
+export async function listFiles(
bucket: Buckets,
folder?: string,
paged?: {
@@ -259,7 +256,7 @@ export async function listS3Files(
* move or copy (or rename) a file
* @throws usually an {@link S3ServiceException}
*/
-export async function moveS3File({
+export async function moveFile({
bucket,
path,
newPath,
@@ -290,7 +287,7 @@ export async function moveS3File({
* create a new empty folder object.
* @throws usually an {@link S3ServiceException}
*/
-export async function createS3Folder(bucket: Buckets, folder: string) {
+export async function createFolder(bucket: Buckets, folder: string) {
await s3.send(
new PutObjectCommand({
Bucket: bucket,
diff --git a/server/tsconfig.json b/server/tsconfig.json
index fb9929a..ae7aec4 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -9,6 +9,7 @@
"esModuleInterop": true,
"moduleResolution": "Bundler",
"incremental": true,
+ "jsx": "react-jsx",
"paths": {
"@@/*": ["./src/*"],
"graphql-modules": ["./node_modules/graphql-modules/index.d.ts"]