-
-
Notifications
You must be signed in to change notification settings - Fork 1
Add Admin API to the backend + more docs and badges #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
ajhalili2006
wants to merge
15
commits into
main
Choose a base branch
from
hackclub/more-hcb-badges
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
088a74a
chore(server): implement response caching to minimize spikes in uncac…
ajhalili2006 74a4cab
chore(vscode): :wrench: update VS Code configs
ajhalili2006 fe00499
chore(global): reformat things and fix some bugs bts
ajhalili2006 719e7e4
chore(deno): update lockfile and tool-versions for asdf
ajhalili2006 15647d9
feat(admin): implement basic auth-check admin api and auth checker
ajhalili2006 4c93423
chore(api): update caching configs and add bearer auth
ajhalili2006 c4f36f9
chore(global): update configs as usual
ajhalili2006 a84c161
refactor(coderabbit): :bug: refractor and squash bugs as flagged by @…
ajhalili2006 2ba7999
chore(vscode): add coderabbiit as scope for conventional commits
ajhalili2006 787ee86
docs(global): add docs for `deno run` scripts and update API ToS
ajhalili2006 ef8bbe2
chore(db): extract DbResult["result"] object type into seperate type …
ajhalili2006 2740b2a
docs(readme): update readme and add contributing guidelines
ajhalili2006 4d6da15
chore(api): implement more backend changes from @coderabbitai suggest…
ajhalili2006 90646ea
docs(readme): update links and stuff
ajhalili2006 0c90caf
fix(admin): some bug squashing on auth checks and then some
ajhalili2006 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
node_modules | ||
.env.keys | ||
secrets/ | ||
.env.decrypted | ||
*.decrypted |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
deno 2.0.4 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"recommendations": [ | ||
"denoland.vscode-deno", | ||
"vivaxy.vscode-conventional-commits" | ||
] | ||
} | ||
"recommendations": [ | ||
"denoland.vscode-deno", | ||
"vivaxy.vscode-conventional-commits" | ||
] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Contributing guidelines | ||
|
||
Thanks for your interest in contributing into the project! If you want to contribute, here | ||
are the documentation you need to get you set up. | ||
|
||
## Pre-flight | ||
|
||
- [ ] Agree to [the Community Code of Conduct](https://policies.recaptime.dev/code-of-conduct) | ||
and [Developer Certificate of Origin](https://developercertificate.org/) | ||
- [ ] Install Deno 2 and Node.js LTS 22.x on your machine (or use Dev Containers / Codespaces instead) | ||
- [ ] You might also need to install dotenvx via npm: `npm i -g @dotenvx/dotenvx` | ||
|
||
## Commit message style | ||
|
||
Our commit message style uses Conventional Commits with the scopes being defined under the | ||
`conventionalCommits.scopes` VS Code workspace configuration. We'll be working on setting up | ||
Commitlint + Commitizen CLI integration soon. | ||
|
||
## Sending patches | ||
|
||
Since we automatically deploy the main branch to production via Deno Deploy, we use GitHub to | ||
accept merge requests although we can also accept on its GitLab mirror and via sourcehut lists. | ||
|
||
### Via sourcehut lists | ||
|
||
> **New to sending email patches?** Visit <https://git-send-email.io/> for a guided tutorial. | ||
|
||
For the subject prefix, please set `format.subjectPrefix` local Git config to `PATCH badges-api` if you are sending | ||
it to dedicated dev mailing list for Community Lorebooks. Otherwise, set it to `PATCH lorebooks-wiki/bdges-api` | ||
for the main dev mailing list at Recap Time Squad. | ||
|
||
Before sending over email, set `sendemail.to` to either `~recaptime-dev/[email protected]` | ||
or `~recaptime-dev/[email protected]` and enable `--annotate` by default with setting `sendemail.annotate` | ||
to `yes` globally. | ||
|
||
```bash | ||
git config sendemail.to ~recaptime-dev/[email protected] | ||
git config format.subjectPrefix "PATH badges-api" | ||
git config format.signOff yes # don't forget to sign-off your commits | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,40 @@ | ||
# Badges API for lorebooks.wiki | ||
# Community Lorebooks Badges API | ||
|
||
[](https://hackclub.com/arcade) | ||
[](https://hcb.hackclub.com/donations/start/recaptime-dev) | ||
|
||
It's like our own instance of `img.shields.io`, but hosted in Deno Deploy with: | ||
|
||
* `hono` and `chanfana` for API docs, validation and routing | ||
* Deno KV for storing badge metadata | ||
* `badges-maker` npm library for generating badges on the fly | ||
- `hono` and `chanfana` for API docs, validation and routing | ||
- Deno KV for storing badge metadata, lessening the URL parameter spaghetti | ||
- `badges-maker` npm library for generating badges on the fly | ||
- Edge caching with the Web Cache API (enabled as a Hono middleware) | ||
|
||
You can see the API docs at <https://badges.api.lorebooks.wiki/docs> or | ||
[explore our docs here](./docs/) | ||
|
||
## Want to use Hack Club Arcade 2024 badge(s) in your README? | ||
## Want to use Hack Club badge(s) in your README? | ||
|
||
See [`docs/hackclub-badges.md`](./docs/hackclub-badges.md) for more details! | ||
See [`docs/hackclub-badges.md`](./docs/hackclub-badges.md) for more details! We'll be adding | ||
more YSWS badges alongside HCB and Hack Club community badges in the future, but you can | ||
request one today. | ||
|
||
## Running locally | ||
|
||
> **:warning: Warning**: You need to either reset the `.env*` files and provide your own | ||
> secrets or ask @ajhalili2006 for the contents of `.env.keys` to decrypt them via | ||
> `dotenvx` in order to locally run the server. | ||
|
||
```bash | ||
deno task dev | ||
dotenvx run -f .env -- deno task dev | ||
``` | ||
|
||
It will listen on `localhost:8080` by default unless overriden by `PORT` | ||
environment variable. | ||
|
||
[See the docs](./docs/self-hosting.md) for a more detailed instructions on self-hosting | ||
and more. | ||
|
||
## License | ||
|
||
AGPL |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import { Bool, Num, OpenAPIRoute, Str } from "chanfana"; | ||
import { Context } from "hono"; | ||
import { z } from "zod"; | ||
import { github, handleGitHubAuth, hashToken, UserDataOps } from "../lib/githubAuth.ts"; | ||
import { kv } from "../lib/db.ts"; | ||
import { config } from "../lib/config.ts"; | ||
|
||
const { authServiceToken, org, team_slug } = config.github; | ||
const ghApi = github(authServiceToken) | ||
|
||
export class testGitHubAuth extends OpenAPIRoute { | ||
override schema = { | ||
tags: ["admin"], | ||
summary: "Check if you are authenticated or not", | ||
description: "To avoid wasting GitHub API requests, we'll cache the API results on KV for 5 minutes. You can also use this endpoint to clear the cache by add `?force=true` URL parameter.", | ||
security: [ | ||
{ | ||
BearerAuth: [], | ||
}, | ||
], | ||
request: { | ||
query: z.object({ | ||
force: Bool({ | ||
description: "Force checking permissions for authenticated user even if cached.", | ||
default: false, | ||
required: false | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
override async handle(c: Context) { | ||
const { query } = await this.getValidatedData<typeof this.schema>(); | ||
const authHeader = c.req.header("Authorization") | ||
const parsedAuthHeader = authHeader?.split(" ") || ["bearer", "null"]; | ||
const tokHash = await hashToken(parsedAuthHeader[1]); | ||
const key = ["cachedGitHubTokenHash", tokHash]; | ||
|
||
|
||
if (parsedAuthHeader[1] == "null") { | ||
return c.json({ | ||
ok: false, | ||
error: { | ||
code: "MISSING_AUTH", | ||
message: "Authorization header is required" | ||
} | ||
}, 401) | ||
} | ||
|
||
const result = await handleGitHubAuth(parsedAuthHeader[1], true, query?.force ?? false) | ||
|
||
try { | ||
const dbMeta = await (await kv(config.kvUrl)).get<UserDataOps>(key) | ||
return c.json({ | ||
ok: result, | ||
result: dbMeta.value ?? null | ||
}) | ||
} catch (error) { | ||
console.error('KV store error:', error); | ||
return c.json({ | ||
ok: result, | ||
result: null, | ||
error: { | ||
code: "KV_ERROR", | ||
message: "Failed to retrieve cached data" | ||
} | ||
}, 500) | ||
} | ||
} | ||
} | ||
|
||
export class grantAdminAccess extends OpenAPIRoute { | ||
override schema = { | ||
tags: ["admin"], | ||
summary: "Add a GitHub user to the API admins team", | ||
description: `\ | ||
Grant a GitHub user access to Badges API admin endpoints by adding them into [the API admins team](https://github.com/orgs/${config.github.org}/teams/${config.github.team_slug}). | ||
|
||
If they are not yet in the \`${config.github.org}\` GitHub organization, they'll be needed to accept the organization invite first.`, | ||
request: { | ||
query: z.object({ | ||
username: Str({ | ||
description: "The GitHub user to grant admin permissions", | ||
required: true | ||
}), | ||
force: Bool({ | ||
description: "Force checking permissions for authenticated user even if cached.", | ||
default: false, | ||
required: false | ||
}) | ||
}) | ||
}, | ||
responses: { | ||
"200": { | ||
description: "Successfully added/invited a user to the team", | ||
content: { | ||
"application/json": { | ||
schema: z.object({ | ||
ok: Bool({ default: true }).default(true), | ||
result: z.object({ | ||
message: Str({ default: "Successfully added" }), | ||
ghApiResult: z.object({ | ||
url: Str({ example: "https://api.github.com/organizations/78218015/team/10816194/memberships/username" }), | ||
role: Str({ example: "member" }), | ||
state: Str({ example: "pending" }) | ||
}), | ||
ghApiStatus: Num({ default: 200 }) | ||
}) | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
override async handle(c: Context) { | ||
try { | ||
const { query } = await this.getValidatedData<typeof this.schema>(); | ||
const apiResult = await ghApi.teams.addOrUpdateMembershipForUserInOrg({ | ||
org, | ||
team_slug, | ||
username: query.username | ||
}) | ||
|
||
return c.json({ | ||
ok: true, | ||
result: { | ||
message: "Successfully added", | ||
ghApiResult: apiResult.data, | ||
ghApiStatus: apiResult.status | ||
} | ||
}) | ||
} catch (error) { | ||
return c.json({ | ||
ok: false, | ||
error: { | ||
code: "GITHUB_API_ERROR", | ||
message: "Something went wrong while adding into the API admins team.", | ||
ghApiResult: error.response.data, | ||
ghApiStatusCode: error.status | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
|
||
export class revokeAdminAccess extends OpenAPIRoute { | ||
// TODO: Implement this | ||
} | ||
|
||
export class getAdminUserInfo extends OpenAPIRoute { | ||
// TODO: Implement this | ||
} | ||
|
||
export class listAdmins extends OpenAPIRoute { | ||
// TODO: Implement this | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.