Skip to content

Commit 6199449

Browse files
authored
Merge pull request #14 from solana-developers/adding-github-endpoint
adding github validation API
2 parents 24d8b4a + eda8134 commit 6199449

File tree

5 files changed

+91
-7
lines changed

5 files changed

+91
-7
lines changed

.github/workflows/deploy.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
- name: Replace app.yml secrets
4040
4141
env:
42-
POSTGRES_STRING: ${{ secrets.POSTGRES_STRING }} # Format: postgres://user:password@/cloudsql/INSTANCE_CONNECTION_NAME/db_name
42+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
4343
PROJECT_ID: ${{ secrets.PROJECT_ID }}
4444
DB_USER: ${{ secrets.DB_USER}}
4545
DB_NAME: ${{ secrets.DB_NAME}}

README.md

+34-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ This API provides endpoints for interacting with two main tables: `faucet.solana
44
Below are the available endpoints for each table.
55

66
---
7-
8-
## How to Run
7+
## Development
98

109
1. Clone the repository
1110
```bash
@@ -22,8 +21,17 @@ Below are the available endpoints for each table.
2221
POSTGRES_STRING=postgresql://<user>:<password>@<host>:<port>/<database>
2322
PROJECT_ID=<GCP Project ID>
2423
```
24+
**NOTE** if you want to send request directly to Analytics DB, use [Cloud SQL Auth Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) to setup a connection
25+
```
26+
./cloud-sql-proxy --address 0.0.0.0 --port 5434 <SQL DB Connection String>
27+
```
28+
29+
4. **OPTIONAL** In order to test the Github API locally, you need to provide a [Github Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) in your `.env` file. The token only needs `read:user` and `public_repo`
30+
```
31+
GH_TOKEN=<Github Token>
32+
```
2533
26-
4. Start the server
34+
5. Start the server
2735
```bash
2836
yarn start
2937
```
@@ -211,6 +219,29 @@ Below are the available endpoints for each table.
211219

212220
---
213221

222+
## Github Validation Endpoints
223+
224+
### **Validate Github User ID**
225+
226+
**GET** `/api/github-validation/:userId`
227+
228+
- **Description**: Validates a Github user by fetching their information from the Github API using their user ID.
229+
- **Request Params**:
230+
- `userId` (string): The Github User ID to validate.
231+
232+
- **Curl Command**:
233+
```bash
234+
curl -v http://localhost:3000/api/gh-validation/exampleUser
235+
```
236+
-**Response**:
237+
```json
238+
{
239+
"valid": "boolean"
240+
}
241+
```
242+
243+
---
244+
214245
## Error Handling
215246

216247
All endpoints return appropriate HTTP status codes:

app.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ entrypoint: yarn start
1111

1212
# Environment variables (replace with your actual values or secrets)
1313
env_variables:
14-
POSTGRES_STRING: $POSTGRES_STRING
14+
GH_TOKEN: GH_TOKEN
1515
PROJECT_ID: $PROJECT_ID
1616
DB_USER: $DB_USER
1717
DB_NAME: $DB_NAME

src/routes/githubValidationRoute.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import express from "express";
2+
3+
const ACCOUNT_AGE_MINIMUM_DAYS = 30;
4+
const router = express.Router();
5+
6+
const daysSince = (date) => {
7+
const msPerDay = 1000 * 60 * 60 * 24;
8+
return Math.floor((new Date() - new Date(date)) / msPerDay);
9+
};
10+
11+
router.get('/gh-validation/:userId', async (req, res) => {
12+
const { userId } = req.params;
13+
14+
const GH_TOKEN = process.env.GH_TOKEN;
15+
if (!GH_TOKEN) {
16+
return res.status(500).json({ error: "GitHub token not configured." });
17+
}
18+
19+
try {
20+
const response = await fetch(`https://api.github.com/user/${userId}`, {
21+
headers: {
22+
Authorization: `token ${GH_TOKEN}`,
23+
Accept: 'application/vnd.github.v3+json'
24+
}
25+
});
26+
27+
if (!response.ok) {
28+
const error = await response.json();
29+
return res.status(response.status).json({ error: error.message || "GitHub API error." });
30+
}
31+
const userData = await response.json();
32+
let valid;
33+
34+
const accountAge = daysSince(userData.created_at);
35+
valid = accountAge >= ACCOUNT_AGE_MINIMUM_DAYS;
36+
37+
if(!valid){
38+
console.error(`Github User ID ${userId} is invalid. Username: ${userData.login}`)
39+
}
40+
res.status(200).json({
41+
valid,
42+
});
43+
} catch (error) {
44+
console.error("Error calling GitHub API:", error);
45+
res.status(500).json({ error: "Internal server error." });
46+
}
47+
});
48+
49+
export default router;

src/routes/index.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import express from 'express';
22
import rateLimitRoute from './rateLimitRoute.js';
3-
import solanaBalancesRoute from "./solanaBalancesRoute.js"; // Import the rate limit routes
3+
import solanaBalancesRoute from "./solanaBalancesRoute.js";
4+
import githubValidationRoute from "./githubValidationRoute.js";
45

56
const router = express.Router();
67

78
// Use rate limit routes
89
router.use(rateLimitRoute);
910

10-
// Use solana balances routes
11+
// Use Solana balances routes
1112
router.use(solanaBalancesRoute);
1213

14+
// Use Github validation routes
15+
router.use(githubValidationRoute);
16+
1317
export default router;

0 commit comments

Comments
 (0)