Skip to content

Commit

Permalink
Merge branch 'main' into support-minio
Browse files Browse the repository at this point in the history
  • Loading branch information
devleejb committed Nov 17, 2024
2 parents 99e5bcc + 7eb889b commit 7a54f6a
Show file tree
Hide file tree
Showing 40 changed files with 3,405 additions and 456 deletions.
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ if [ "$LINT_BACKEND" = true ]; then
exit 1
fi
cd ..
fi
fi
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,69 @@ and CodePair adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

## [0.1.23] - 2024-11-10

### Changed

- Update `yorkie-js-sdk` to `v0.5.5` by @devleejb in https://github.com/yorkie-team/codepair/pull/407

## [0.1.22] - 2024-11-05

### Added

- Add `throttle` to prevent preview's indiscriminate updates by @JOOHOJANG in https://github.com/yorkie-team/codepair/pull/391

## [0.1.21] - 2024-11-05

### Added

- Add markdown render checkbox plugin by @blurfx in https://github.com/yorkie-team/codepair/pull/400
- Add Envs for Github Enterprise Oauth App by @emplam27 in https://github.com/yorkie-team/codepair/pull/404

## [0.1.20] - 2024-11-04

### Added

- Add option to toggle Scroll Sync On/Off by @devleejb in https://github.com/yorkie-team/codepair/pull/394

### Changed

- Apply incremental dom update by @blurfx in https://github.com/yorkie-team/codepair/pull/397
- Update `yorkie-js-sdk` to `v0.5.4` by @devleejb in https://github.com/yorkie-team/codepair/pull/390

### Fixed

- Fix ESLint Rules to Ensure Proper Code Compliance by @devleejb in https://github.com/yorkie-team/codepair/pull/392
- Fix cursor movement logic during Snapshot Event by @devleejb in https://github.com/yorkie-team/codepair/pull/398

## [0.1.19] - 2024-10-28

### Fixed

- Disable model checking when intelligence is `false` by @devleejb in https://github.com/yorkie-team/codepair/pull/388

## [0.1.18] - 2024-10-26

### Changed

- Change default `syncLoopDuration` and Expose `yorkie.Document` by @devleejb in https://github.com/yorkie-team/codepair/pull/386

## [0.1.17] - 2024-10-25

### Changed

- Disable devtools by @hackerwins in https://github.com/yorkie-team/codepair/pull/383
- Activate SourceMap for Sentry and resolve TypeScript version conflict with ESLint by @devleejb in https://github.com/yorkie-team/codepair/pull/384

## [0.1.16] - 2024-10-24

### Changed

- Update `yorkie-js-sdk` to `v0.5.1` by @devleejb in https://github.com/yorkie-team/codepair/pull/369
- Remove model type and refactor code for Yorkie Intelligence by @sihyeong671 in https://github.com/yorkie-team/codepair/pull/374
- Update `yorkie-js-sdk` to `v0.5.2` by @hackerwins in https://github.com/yorkie-team/codepair/pull/380
- Update `yorkie-js-sdk` to `v0.5.3` by @hackerwins in https://github.com/yorkie-team/codepair/pull/381

## [0.1.15] - 2024-10-14

### Added
Expand Down
19 changes: 13 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ If you have any questions along the way, please don’t hesitate to ask us

This is a rough outline of what a contributor's workflow looks like:

- Create a topic branch from where to base the contribution. This is usually main
- Make commits of logical units
- Make sure commit messages are in the proper format
- Push changes in a topic branch to a personal fork of the repository
- Submit a pull request to yorkie-team/codepair
- The PR must receive a LGTM from maintainers
1. Create a topic branch from where to base the contribution (usually main).
2. Make commits of logical units.
- Make sure all tests pass, and add any new tests as appropriate.
- Make sure commit messages are in the proper format (see below).
3. Push changes in a topic branch to the forked repository.
4. Submit a pull request to the original repository.
5. Address any review comments from CodeRabbit and maintainers.
6. After receiving LGTM from maintainers, the PR will be merged.

Thanks for contributing!

Expand Down Expand Up @@ -79,6 +81,11 @@ The first line is the subject and should be no longer than 70 characters, the se
6. **Pull Request**
Submit a pull request for review.

## Code Review

We use GitHub's pull request review feature to review code. We also use CodeRabbit to automate code review for reducing the effort of maintainers. CodeRabbit will automatically review your pull request and provide feedback on code quality, test coverage, and more.
We require that all code is reviewed by at least one maintainer before being merged. We may ask for changes to be made to the code before it is merged.

## Contributor License Agreement

We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution.
Expand Down
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ RUN mkdir /usr/share/fonts/nanumfont && \
fc-cache -f -v

# Set the environment variables
ENV NODE_ENV production
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium-browser

Expand Down
16 changes: 14 additions & 2 deletions backend/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ GITHUB_CLIENT_SECRET=your_github_client_secret_here
# Format: https://<backend_url>/auth/login/github
# Example: http://localhost:3000/auth/login/github (For development mode)
GITHUB_CALLBACK_URL=http://localhost:3000/auth/login/github
# GITHUB_AUTHORIZATION_URL: Authorization URL for Github OAuth app.
# Default OAuth app is Github. Change this url for using Github Enterprise OAuth App.
# Format: https://ENTERPRISE_INSTANCE_URL/login/oauth/authorize
GITHUB_AUTHORIZATION_URL=https://github.com/login/oauth/authorize
# GITHUB_TOKEN_URL: Token URL for Github OAuth app.
# Default OAuth app is Github. Change this url for using Github Enterprise OAuth App.
# https://ENTERPRISE_INSTANCE_URL/login/oauth/access_token
GITHUB_TOKEN_URL=https://github.com/login/oauth/access_token
# GITHUB_USER_PROFILE_URL: User profile URL for Github OAuth app.
# Default OAuth app is Github. Change this url for using Github Enterprise OAuth App.
# https://ENTERPRISE_INSTANCE_URL/api/v3/user
GITHUB_USER_PROFILE_URL=https://api.github.com/user

# JWT_ACCESS_TOKEN_SECRET: Secret key for signing and verifying access tokens.
# JWT_ACCESS_TOKEN_EXPIRATION_TIME: Expiration time for access tokens in seconds.
Expand Down Expand Up @@ -42,9 +54,9 @@ YORKIE_PROJECT_NAME=default
YORKIE_PROJECT_SECRET_KEY=""

# YORKIE_INTELLIGENCE: Whether to enable Yorkie Intelligence for collaborative editing.
# Available options: false, ollama:lamma3.1, ollama:gemma2, ollama:gemma2:2b, ollama:phi3, ollama:mistral, ollama:neural-chat, ollama:starling-lm, ollama:solar, openai:gpt-3.5-turbo, openai:gpt-4o-mini
# Available options: false, ollama:llama3.1, ollama:gemma2, ollama:gemma2:2b, ollama:phi3, ollama:mistral, ollama:neural-chat, ollama:starling-lm, ollama:solar, openai:gpt-3.5-turbo, openai:gpt-4o-mini, etc.
# If set to openai:gpt-3.5-turbo or openai:gpt-4o-mini, OPENAI_API_KEY is not required.
YORKIE_INTELLIGENCE="ollama:gemma2:2b"
YORKIE_INTELLIGENCE="ollama:llama3.2:1b"

# OLLAMA_HOST_URL: yorkie-intelligence ollama url
OLLAMA_HOST_URL=http://localhost:11434
Expand Down
2 changes: 1 addition & 1 deletion backend/docker/docker-compose-full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ services:
- "minio:minio"

yorkie:
image: "yorkieteam/yorkie:0.5.0"
image: "yorkieteam/yorkie:0.5.5"
command: ["server", "--enable-pprof"]
restart: always
ports:
Expand Down
2 changes: 1 addition & 1 deletion backend/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3.8"

services:
yorkie:
image: "yorkieteam/yorkie:0.5.0"
image: "yorkieteam/yorkie:0.5.5"
command: ["server", "--enable-pprof"]
restart: always
ports:
Expand Down
2 changes: 2 additions & 0 deletions backend/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export default [
prettier: prettierPlugin,
},
rules: {
...typescriptPlugin.configs.recommended.rules,
...prettierPlugin.configs.recommended.rules,
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
Expand Down
3 changes: 2 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "@codepair/backend",
"version": "0.1.15",
"version": "0.1.23",
"description": "CodePair Backend",
"author": "yorkie-team",
"license": "Apache-2.0",
"scripts": {
"build": "nest build",
"postinstall": "pnpm run db:generate",
"db:generate": "prisma generate --schema=prisma/schema.prisma",
"start": "nest start",
"start:dev": "nest start --watch",
Expand Down
3 changes: 3 additions & 0 deletions backend/src/auth/github.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class GithubStrategy extends PassportStrategy(Strategy, "github") {
clientID: configService.get<string>("GITHUB_CLIENT_ID"),
clientSecret: configService.get<string>("GITHUB_CLIENT_SECRET"),
callbackURL: configService.get<string>("GITHUB_CALLBACK_URL"),
authorizationURL: configService.get<string>("GITHUB_AUTHORIZATION_URL"),
tokenURL: configService.get<string>("GITHUB_TOKEN_URL"),
userProfileURL: configService.get<string>("GITHUB_USER_PROFILE_URL"),
scope: ["public_profile"],
});
}
Expand Down
115 changes: 71 additions & 44 deletions backend/src/check/check.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from "@nestjs/common";
import { ForbiddenException, Injectable, UnauthorizedException } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import * as moment from "moment";
import { PrismaService } from "src/db/prisma.service";
Expand Down Expand Up @@ -33,64 +33,91 @@ export class CheckService {
}

async checkYorkie(checkYorkieDto: CheckYorkieDto): Promise<CheckYorkieResponse> {
let reason = "";
let allowed = false;
const [type, token] = checkYorkieDto.token.split(":");

// In `ActivateClient`, `DeactivateClient` methods, the `checkYorkieDto.attributes` is empty.
if (
[YorkieMethod.ActivateClient, YorkieMethod.DeactivateClient].includes(
checkYorkieDto.method
)
) {
allowed = true;
reason = `Pass ${checkYorkieDto.method}`;
return {
allowed: true,
reason: `Pass ${checkYorkieDto.method} method`,
};
}

const { key: yorkieDocumentId } = checkYorkieDto.attributes?.[0];
if (type == "default") {
await this.checkDefaultAccessToken(yorkieDocumentId, token);
} else if (type == "share") {
await this.checkSharingAccessToken(yorkieDocumentId, token);
} else {
const { key: yorkieDocumentId } = checkYorkieDto.attributes?.[0];
if (type === "default") {
const { sub } = this.jwtService.verify<JwtPayload>(token);
throw new ForbiddenException({ allowed: false, reason: "Invalid token type" });
}

const res = await this.prismaService.document.findFirst({
select: {
id: true,
},
where: {
yorkieDocumentId,
workspace: {
userWorkspaceList: {
every: {
userId: sub,
},
},
return {
allowed: true,
reason: "Valid token",
};
}

private async checkDefaultAccessToken(
yorkieDocumentId: string,
accessToken: string
): Promise<string> {
let sub = "";
try {
sub = this.jwtService.verify<JwtPayload>(accessToken).sub;
} catch {
throw new UnauthorizedException({
allowed: false,
reason: "Token is expired or invalid",
});
}

const document = await this.prismaService.document.findFirst({
select: {
id: true,
},
where: {
yorkieDocumentId,
workspace: {
userWorkspaceList: {
every: {
userId: sub,
},
},
});
},
},
});

allowed = Boolean(res);
} else if (type === "share") {
const documentSharingToken =
await this.prismaService.documentSharingToken.findFirst({
where: {
token,
document: {
yorkieDocumentId,
},
},
});
if (!document) {
throw new ForbiddenException({
allowed: false,
reason: "User does not have access to the document",
});
}

return sub;
}

allowed = Boolean(documentSharingToken);
private async checkSharingAccessToken(yorkieDocumentId: string, accessToken: string) {
const documentSharingToken = await this.prismaService.documentSharingToken.findFirst({
where: {
token: accessToken,
document: {
yorkieDocumentId,
},
},
});

if (
documentSharingToken?.expiredAt &&
moment().isAfter(documentSharingToken?.expiredAt)
) {
allowed = false;
}
}
if (!documentSharingToken) {
throw new ForbiddenException({ allowed: false, reason: "Sharing token is invalid" });
}

return {
allowed,
reason,
};
if (documentSharingToken?.expiredAt && moment().isAfter(documentSharingToken?.expiredAt)) {
throw new ForbiddenException({ allowed: false, reason: "Sharing token is expired" });
}
}
}
2 changes: 0 additions & 2 deletions backend/src/documents/documents.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ describe("DocumentsService", () => {
});

it("should be defined", async () => {
prismaService;

expect(documentsService).toBeDefined();
});

Expand Down
4 changes: 2 additions & 2 deletions backend/src/documents/documents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class DocumentsService {
) {
throw new Error();
}
} catch (e) {
} catch {
throw new UnauthorizedException("Invalid sharing token");
}

Expand All @@ -42,7 +42,7 @@ export class DocumentsService {
id: documentId,
},
});
} catch (e) {
} catch {
throw new NotFoundException("Document not found");
}

Expand Down
3 changes: 2 additions & 1 deletion backend/src/files/files.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
Redirect,
StreamableFile,
} from "@nestjs/common";
import { ApiBody, ApiOkResponse, ApiOperation, ApiResponse } from "@nestjs/swagger";
import { ApiBody, ApiOkResponse, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { Public } from "src/utils/decorators/auth.decorator";
import { CreateUploadPresignedUrlDto } from "./dto/create-upload-url.dto";
import { FilesService } from "./files.service";
import { CreateUploadPresignedUrlResponse } from "./types/create-upload-url-response.type";
import { ExportFileRequestBody, ExportFileResponse } from "./types/export-file.type";

@ApiTags("Files")
@Controller("files")
export class FilesController {
constructor(private filesService: FilesService) {}
Expand Down
Loading

0 comments on commit 7a54f6a

Please sign in to comment.