Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/docker-build-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ jobs:

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Create .env file
run: |
echo "WEB_URL=http://localhost:3000" > .env
echo "NEXT_PUBLIC_CAP_AWS_BUCKET=capso" >> .env
echo "NEXT_PUBLIC_CAP_AWS_REGION=us-east-1" >> .env
cat .env

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
Expand Down
2 changes: 1 addition & 1 deletion apps/web/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker.io/docker/dockerfile:1

FROM node:20-alpine AS base
FROM node:22-alpine AS base
RUN corepack enable

FROM base AS builder
Expand Down
4 changes: 3 additions & 1 deletion apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getCurrentUser } from "@cap/database/auth/session";
import { buildEnv, serverEnv } from "@cap/env";
import { S3_BUCKET_URL } from "@cap/utils";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import crypto from "crypto";
import crypto from "node:crypto";
import type { Metadata } from "next";
import { PropsWithChildren } from "react";
import { AuthProvider } from "./AuthProvider";
Expand All @@ -31,6 +31,8 @@ export const metadata: Metadata = {
},
};

export const dynamic = "force-dynamic";

export default async function RootLayout({ children }: PropsWithChildren) {
const user = await getCurrentUser();
const bootstrapData = await getBootstrapData();
Expand Down
12 changes: 10 additions & 2 deletions apps/web/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// It is not suitable (a.k.a DEADLY) for serverless environments where the server will be restarted on each request.

import { serverEnv } from "@cap/env";
import { createS3Client } from "./utils/s3";
import {
BucketAlreadyOwnedByYou,
CreateBucketCommand,
PutBucketPolicyCommand,
S3Client,
} from "@aws-sdk/client-s3";

export async function register() {
Expand Down Expand Up @@ -61,7 +61,15 @@ export async function register() {
}

async function createS3Bucket() {
const [s3Client] = await createS3Client();
const s3Client = new S3Client({
endpoint: serverEnv().CAP_AWS_ENDPOINT,
region: serverEnv().CAP_AWS_REGION,
credentials: {
accessKeyId: serverEnv().CAP_AWS_ACCESS_KEY ?? "",
secretAccessKey: serverEnv().CAP_AWS_SECRET_KEY ?? "",
},
forcePathStyle: serverEnv().S3_PATH_STYLE,
});

await s3Client
.send(new CreateBucketCommand({ Bucket: serverEnv().CAP_AWS_BUCKET }))
Expand Down
28 changes: 14 additions & 14 deletions apps/web/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ export async function middleware(request: NextRequest) {
const hostname = url.hostname;
const path = url.pathname;

if (
buildEnv.NEXT_PUBLIC_IS_CAP !== "true" &&
!(
path.startsWith("/s/") ||
path.startsWith("/dashboard") ||
path.startsWith("/onboarding") ||
path.startsWith("/api") ||
path.startsWith("/login") ||
path.startsWith("/invite") ||
path.startsWith("/self-hosting") ||
path.startsWith("/terms")
if (buildEnv.NEXT_PUBLIC_IS_CAP !== "true") {
if (
!(
path.startsWith("/s/") ||
path.startsWith("/dashboard") ||
path.startsWith("/onboarding") ||
path.startsWith("/api") ||
path.startsWith("/login") ||
path.startsWith("/invite") ||
path.startsWith("/self-hosting") ||
path.startsWith("/terms")
)
)
) {
return NextResponse.redirect(new URL("/login", url.origin));
return NextResponse.redirect(new URL("/login", url.origin));
else return NextResponse.next();
}

if (mainOrigins.some((d) => url.origin.startsWith(d))) {
Expand All @@ -54,7 +55,6 @@ export async function middleware(request: NextRequest) {
if (!path.startsWith("/s/")) {
const url = new URL(request.url);
url.hostname = webUrl;
console.log({ url });
return NextResponse.redirect(url);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,4 @@
"engines": {
"node": "20"
}
}
}
2 changes: 1 addition & 1 deletion apps/web/utils/s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import type { s3Buckets } from "@cap/database/schema";
import type { InferSelectModel } from "drizzle-orm";
import { decrypt } from "@cap/database/crypto";
import { buildEnv, serverEnv } from "@cap/env";
import { serverEnv } from "@cap/env";
import * as S3Presigner from "@aws-sdk/s3-request-presigner";
import * as CloudFrontPresigner from "@aws-sdk/cloudfront-signer";
import { S3_BUCKET_URL } from "@cap/utils";
Expand Down
7 changes: 5 additions & 2 deletions packages/database/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { serverEnv } from "@cap/env";
import { timingSafeEqual } from "crypto";
import { timingSafeEqual } from "node:crypto";

const ALGORITHM = { name: "AES-GCM", length: 256 };
const IV_LENGTH = 12;
Expand Down Expand Up @@ -162,7 +162,10 @@ export async function hashPassword(password: string): Promise<string> {
return result.toString("base64");
}

export async function verifyPassword(stored: string, password: string): Promise<boolean> {
export async function verifyPassword(
stored: string,
password: string
): Promise<boolean> {
if (!stored || !password) return false;

const data = Buffer.from(stored, "base64");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,4 @@ CREATE INDEX `owner_id_idx` ON `spaces` (`ownerId`);--> statement-breakpoint
CREATE INDEX `custom_domain_idx` ON `spaces` (`customDomain`);--> statement-breakpoint
CREATE INDEX `id_idx` ON `videos` (`id`);--> statement-breakpoint
CREATE INDEX `owner_id_idx` ON `videos` (`ownerId`);--> statement-breakpoint
CREATE INDEX `is_public_idx` ON `videos` (`public`);
CREATE INDEX `is_public_idx` ON `videos` (`public`);
29 changes: 0 additions & 29 deletions packages/database/migrations/0001_eager_the_order.sql

This file was deleted.

39 changes: 39 additions & 0 deletions packages/database/migrations/0001_white_young_avengers.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
CREATE TABLE `auth_api_keys` (
`id` varchar(36) NOT NULL,
`userId` varchar(15) NOT NULL,
`createdAt` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `auth_api_keys_id` PRIMARY KEY(`id`),
CONSTRAINT `auth_api_keys_id_unique` UNIQUE(`id`)
);
--> statement-breakpoint
RENAME TABLE `space_invites` TO `organization_invites`;--> statement-breakpoint
RENAME TABLE `space_members` TO `organization_members`;--> statement-breakpoint
RENAME TABLE `spaces` TO `organizations`;--> statement-breakpoint
ALTER TABLE `shared_videos` RENAME COLUMN `spaceId` TO `organizationId`;--> statement-breakpoint
ALTER TABLE `organization_invites` RENAME COLUMN `spaceId` TO `organizationId`;--> statement-breakpoint
ALTER TABLE `organization_members` RENAME COLUMN `spaceId` TO `organizationId`;--> statement-breakpoint
ALTER TABLE `users` RENAME COLUMN `activeSpaceId` TO `activeOrganizationId`;--> statement-breakpoint
ALTER TABLE `organization_invites` DROP INDEX `space_invites_id_unique`;--> statement-breakpoint
ALTER TABLE `organization_members` DROP INDEX `space_members_id_unique`;--> statement-breakpoint
ALTER TABLE `organizations` DROP INDEX `spaces_id_unique`;--> statement-breakpoint
DROP INDEX `space_id_idx` ON `shared_videos`;--> statement-breakpoint
DROP INDEX `video_id_space_id_idx` ON `shared_videos`;--> statement-breakpoint
DROP INDEX `space_id_idx` ON `organization_invites`;--> statement-breakpoint
DROP INDEX `space_id_idx` ON `organization_members`;--> statement-breakpoint
DROP INDEX `user_id_space_id_idx` ON `organization_members`;--> statement-breakpoint
ALTER TABLE `organization_invites` DROP PRIMARY KEY;--> statement-breakpoint
ALTER TABLE `organization_members` DROP PRIMARY KEY;--> statement-breakpoint
ALTER TABLE `organizations` DROP PRIMARY KEY;--> statement-breakpoint
ALTER TABLE `organization_invites` ADD PRIMARY KEY(`id`);--> statement-breakpoint
ALTER TABLE `organization_members` ADD PRIMARY KEY(`id`);--> statement-breakpoint
ALTER TABLE `organizations` ADD PRIMARY KEY(`id`);--> statement-breakpoint
ALTER TABLE `organizations` ADD `iconUrl` varchar(1024);--> statement-breakpoint
ALTER TABLE `videos` ADD `password` text;--> statement-breakpoint
ALTER TABLE `organization_invites` ADD CONSTRAINT `organization_invites_id_unique` UNIQUE(`id`);--> statement-breakpoint
ALTER TABLE `organization_members` ADD CONSTRAINT `organization_members_id_unique` UNIQUE(`id`);--> statement-breakpoint
ALTER TABLE `organizations` ADD CONSTRAINT `organizations_id_unique` UNIQUE(`id`);--> statement-breakpoint
CREATE INDEX `organization_id_idx` ON `shared_videos` (`organizationId`);--> statement-breakpoint
CREATE INDEX `video_id_organization_id_idx` ON `shared_videos` (`videoId`,`organizationId`);--> statement-breakpoint
CREATE INDEX `organization_id_idx` ON `organization_invites` (`organizationId`);--> statement-breakpoint
CREATE INDEX `organization_id_idx` ON `organization_members` (`organizationId`);--> statement-breakpoint
CREATE INDEX `user_id_organization_id_idx` ON `organization_members` (`userId`,`organizationId`);
1 change: 0 additions & 1 deletion packages/database/migrations/0002_powerful_scourge.sql

This file was deleted.

5 changes: 0 additions & 5 deletions packages/database/migrations/0003_small_chamber.sql

This file was deleted.

2 changes: 0 additions & 2 deletions packages/database/migrations/0004_good_microbe.sql

This file was deleted.

1 change: 0 additions & 1 deletion packages/database/migrations/0005_jazzy_brood.sql

This file was deleted.

1 change: 0 additions & 1 deletion packages/database/migrations/0005_password_protection.sql

This file was deleted.

Loading
Loading