@on("github.pull_request")
def agent(input):
pass
{
"$raw": {},
"action": "opened",
"author": "developer123",
"changes": [
{
"additions": 25,
"changes": 35,
"deletions": 10,
"filename": "src/services/auth.ts",
"patch": "@@ -15,10 +15,25 @@ export class AuthService {\n private async validateToken(token: string) {\n- // Basic auth validation\n- const [username, password] = Buffer.from(token, 'base64')\n- .toString()\n- .split(':');\n-\n- return this.validateCredentials(username, password);\n+ try {\n+ const decoded = jwt.verify(token, this.config.jwt_secret) as JwtPayload;\n+ \n+ if (!decoded.sub || !decoded.exp) {\n+ throw new Error('Invalid token structure');\n+ }\n+ \n+ if (decoded.exp < Date.now() / 1000) {\n+ throw new Error('Token has expired');\n+ }\n+ \n+ const user = await this.userService.findById(decoded.sub);\n+ if (!user) {\n+ throw new Error('User not found');\n+ }\n+ \n+ if (!user.active) {\n+ throw new Error('User account is disabled');\n+ }\n+ \n+ return user;\n+ } catch (error) {\n+ throw new AuthenticationError('Invalid or expired token');\n+ }\n }",
"status": "modified"
},
{
"additions": 50,
"changes": 50,
"deletions": 0,
"filename": "tests/auth.test.ts",
"patch": "@@ -0,0 +1,50 @@\n+import { describe, it, expect, jest } from 'jest';\n+import { AuthService } from '../src/services/auth';\n+import { UserService } from '../src/services/user';\n+import { AuthenticationError } from '../src/errors';\n+\n+describe('AuthService', () => {\n+ let authService: AuthService;\n+ let userService: jest.Mocked<UserService>;\n+\n+ beforeEach(() => {\n+ userService = {\n+ findById: jest.fn(),\n+ } as any;\n+\n+ authService = new AuthService({\n+ jwt_secret: 'test-secret',\n+ token_expiry: '1h'\n+ }, userService);\n+ });\n+\n+ describe('validateToken', () => {\n+ it('should successfully validate a valid token', async () => {\n+ const mockUser = {\n+ id: '123',\n+ active: true,\n+ name: 'Test User'\n+ };\n+\n+ userService.findById.mockResolvedValue(mockUser);\n+\n+ const token = authService.generateToken(mockUser);\n+ const result = await authService.validateToken(token);\n+\n+ expect(result).toEqual(mockUser);\n+ expect(userService.findById).toHaveBeenCalledWith('123');\n+ });\n+\n+ it('should throw on expired token', async () => {\n+ const mockUser = {\n+ id: '123',\n+ active: true,\n+ name: 'Test User'\n+ };\n+\n+ // Generate token that's already expired\n+ const token = authService.generateToken(mockUser, '-1h');\n+\n+ await expect(authService.validateToken(token))\n+ .rejects\n+ .toThrow(AuthenticationError);\n+ });\n+ });\n+});",
"status": "added"
},
{
"additions": 15,
"changes": 20,
"deletions": 5,
"filename": "README.md",
"patch": "@@ -10,8 +10,18 @@ ## Authentication\n-### Basic Authentication\n-To authenticate requests, provide your credentials in the Authorization header:\n-\n-```\n-Authorization: Basic base64(username:password)\n-```\n+### OAuth2 Authentication\n+\n+This API uses OAuth2 for authentication. To authenticate requests, include a Bearer token in the Authorization header:\n+\n+```\n+Authorization: Bearer <your_token>\n+```\n+\n+#### Obtaining a Token\n+\n+1. Redirect users to `/oauth/authorize`\n+2. Users approve the application\n+3. Exchange the authorization code for a token at `/oauth/token`\n+\n+Tokens expire after 1 hour. Use the refresh token to obtain a new access token.\n+\n+For more details, see our [OAuth2 Implementation Guide](./docs/oauth2.md).",
"status": "modified"
}
],
"commit_message": "feat: implement OAuth2 authentication",
"commit_sha": "abc123def456789ghijklmnop",
"files_changed": [
"src/services/auth.ts",
"tests/auth.test.ts",
"README.md"
],
"owner": "octocat",
"pull_request": {
"author": "developer123",
"body": "This PR adds OAuth2 authentication support and removes the basic auth implementation.\n\nChanges:\n- Replaces basic auth with JWT-based OAuth2\n- Adds comprehensive tests\n- Updates documentation\n- Adds token validation and expiry handling\n\nPlease review the token expiry duration and error messages.",
"comments": [
{
"author": "reviewer456",
"body": "Could you add some documentation about token refresh flows? Particularly around handling expired refresh tokens.",
"created_at": "2024-03-21T11:30:00Z",
"diff_hunk": "@@ -15,7 +15,12 @@ export class AuthService {\n private async validateToken(token: string) {\n- // Basic auth validation\n- const [username, password] = Buffer.from(token, 'base64')\n- .toString()\n- .split(':');\n-\n- return this.validateCredentials(username, password);\n+ try {\n+ const decoded = jwt.verify(token, this.config.jwt_secret) as JwtPayload;",
"filename": "src/services/auth.ts",
"id": 444555666,
"line": 17,
"node_id": "PRRC_kwDOA3333333333",
"original_line": 2,
"original_position": 2,
"original_start_line": 15,
"start_line": 17,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555666"
},
{
"author": "security-reviewer",
"body": "We should add a check for token blacklisting here in case we need to revoke access.",
"created_at": "2024-03-21T12:15:00Z",
"diff_hunk": "@@ -20,6 +20,11 @@ export class AuthService {\n if (!decoded.sub || !decoded.exp) {\n throw new Error('Invalid token structure');\n }\n+ \n+ if (decoded.exp < Date.now() / 1000) {\n+ throw new Error('Token has expired');\n+ }\n+ \n+ const user = await this.userService.findById(decoded.sub);",
"filename": "src/services/auth.ts",
"id": 444555667,
"line": 25,
"node_id": "PRRC_kwDOA3333333334",
"original_line": null,
"original_position": 5,
"original_start_line": null,
"start_line": 25,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555667"
},
{
"author": "developer123",
"body": "Good catch! I'll add the blacklist check in the next commit.",
"created_at": "2024-03-21T12:30:00Z",
"diff_hunk": "@@ -25,6 +25,10 @@ export class AuthService {\n if (decoded.exp < Date.now() / 1000) {\n throw new Error('Token has expired');\n }\n+ \n+ const user = await this.userService.findById(decoded.sub);\n+ if (!user) {\n+ throw new Error('User not found');\n+ }",
"filename": "src/services/auth.ts",
"id": 444555668,
"line": 28,
"node_id": "PRRC_kwDOA3333333335",
"original_line": null,
"original_position": 8,
"original_start_line": null,
"start_line": 28,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555668"
}
],
"created_at": "2024-03-21T10:00:00Z",
"id": 987654321,
"labels": [
{
"color": "84b6eb",
"default": true,
"description": "New feature or request",
"id": 111222,
"name": "enhancement",
"node_id": "LA_kwDOA1111111111"
},
{
"color": "d93f0b",
"default": false,
"description": "Security related changes",
"id": 333444,
"name": "security",
"node_id": "LA_kwDOA2222222222"
}
],
"node_id": "PR_kwDOA1234567890",
"number": 123,
"state": "open",
"title": "Implement OAuth2 Authentication",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/123"
},
"ref": "feature/oauth-auth",
"repo": "Hello-World"
}
def agent(input):
$raw = input.get("$raw")
action = input.get("action")
author = input.get("author")
changes = input.get("changes")
commit_message = input.get("commit_message")
commit_sha = input.get("commit_sha")
files_changed = input.get("files_changed")
owner = input.get("owner")
pull_request = input.get("pull_request")
ref = input.get("ref")
repo = input.get("repo")
Fields
object
The raw Github
pull_request event payload.string
string
The author of the pull request.
change[]
The changes that were made to the files in the pull request.
string
The commit message of the pull request.
string
The SHA of the commit that was used to create the pull request.
string[]
The files that were changed in the pull request.
string
The owner of the repository.
object
The pull request object.
Show pull_request properties
Show pull_request properties
string
The author of the pull request.
string
The body of the pull request.
object[]
The comments on the pull request.
Show comment properties
Show comment properties
string
The author of the comment.
string
The body of the comment.
string
The date and time the comment was created.
string
The diff hunk of the comment.
string
The filename of the file that the comment is on.
number
The ID of the comment.
number
The line number of the comment.
string
The node ID of the comment.
number
The original line number of the comment.
number
The original position of the comment.
number
The original start line of the comment.
number
The start line of the comment.
string
The start side of the comment.
string
The subject type of the comment.
string
The URL of the comment.
string
The date and time the pull request was created.
number
The ID of the pull request.
object[]
string
The node ID of the pull request.
number
The number of the pull request.
string
The state of the pull request.
string
The title of the pull request.
string
The URL of the pull request.
string
The ref of the pull request.
string
The repository of the pull request.

