Skip to content

Commit ccae586

Browse files
authored
Merge branch 'main' into feature/og-meta-tags
Signed-off-by: amritbej.sh <amritbej750@gmail.com>
2 parents 00a9ec9 + 82a70f1 commit ccae586

39 files changed

Lines changed: 4650 additions & 4584 deletions

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ DATABASE_URL=postgresql://devcard:devcard@localhost:5432/devcard?schema=public
44
# ─── Redis ───
55
REDIS_URL=redis://localhost:6379
66

7+
# ─── Set The Url ───
8+
PUBLIC_APP_URL=
9+
710
# ─── JWT ───
811
# JWT_SECRET: any long random string, minimum 32 characters
912
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports = async ({ github, context }) => {
2+
const pr = context.payload.pull_request;
3+
const ignoreUsers = [
4+
'ShantKhatri',
5+
'Harxhit'
6+
]
7+
try {
8+
// Only continue if merged
9+
if (!pr || !pr.merged) {
10+
console.log('PR not merged.');
11+
return;
12+
}
13+
14+
const prNumber = pr.number;
15+
const contributor = pr.user.login;
16+
17+
if(ignoreUsers.includes(contributor)){
18+
console.log(`Ignoring PR #${prNumber} by ${contributor}`);
19+
return;
20+
}
21+
22+
await github.rest.issues.createComment({
23+
owner: context.repo.owner,
24+
repo: context.repo.repo,
25+
issue_number: prNumber,
26+
body: `Congratulations @${contributor} on getting PR #${prNumber} merged!
27+
28+
Thank you for your contribution. Please mention @Harxhit in our Discord server to receive the appropriate GSSoC labels and recognition.
29+
`
30+
});
31+
32+
console.log(`Comment added to PR #${prNumber}`);
33+
} catch (error) {
34+
console.error(error)
35+
}
36+
};

.github/scripts/welcomeScript.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,34 @@ module.exports = async ({ github, context }) => {
1111

1212
if (
1313
eventName === 'issues' &&
14-
issueAssociation === 'FIRST_TIMER'
14+
issueAssociation === 'NONE'
1515
) {
16-
return await github.rest.issues.createComment({
16+
// Verify this is truly their first issue (listForRepo returns PRs too)
17+
const userIssues = await github.rest.issues.listForRepo({
1718
owner,
1819
repo,
19-
issue_number: issueNumber,
20-
body: `👋 Thanks for opening your first issue, @${ghUsername}!
20+
state: 'all',
21+
creator: ghUsername,
22+
per_page: 10
23+
});
24+
25+
const actualIssues = userIssues.data.filter(issue => !issue.pull_request);
26+
27+
if (actualIssues.length === 1) {
28+
return await github.rest.issues.createComment({
29+
owner,
30+
repo,
31+
issue_number: issueNumber,
32+
body: `👋 Thanks for opening your first issue, @${ghUsername}!
2133
2234
We appreciate your contribution and are excited to have you here. Please make sure to follow the contribution guidelines and provide as much detail as possible.
2335
2436
To stay updated, ask questions, and connect with maintainers and contributors, please join our Discord community:
2537
https://discord.gg/QueQN83wn
2638
2739
Looking forward to collaborating with you!`
28-
});
40+
});
41+
}
2942
}
3043

3144
const prAssociation =
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: GSSoC Discord Pin Reminder
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
workflow_dispatch:
7+
8+
jobs:
9+
discord-pin-reminder:
10+
if: github.event.pull_request.merged == true
11+
runs-on: ubuntu-latest
12+
13+
permissions:
14+
pull-requests: write
15+
issues: write
16+
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
20+
21+
- name: Notify contributor about Discord GSSoC labels
22+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
23+
with:
24+
github-token: ${{ secrets.GITHUB_TOKEN }}
25+
script: |
26+
const script = require('./.github/scripts/discordPinReminder.js');
27+
await script({ github, context });

apps/backend/prisma/schema.prisma

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ model TeamMember{
188188
role TeamRole
189189
joinedAt DateTime
190190
191-
team Team @relation("TeamMember",fields: [teamId] , references: [id])
191+
team Team @relation("TeamMember",fields: [teamId] , references: [id], onDelete: Cascade)
192192
user User @relation("TeamMember",fields: [userId] , references: [id])
193193
194194
@@unique([userId, teamId])

apps/backend/src/routes/auth.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ export async function authRoutes(app: FastifyInstance) {
5757
// GitHub OAuth callback
5858
app.get('/github/callback', async (request: FastifyRequest<{ Querystring: OAuthCallbackQuery }>, reply: FastifyReply) => {
5959
const { code, state } = request.query;
60-
const storedState = (request.cookies as any)?.oauth_state;
61-
60+
const storedState = request.cookies?.oauth_state;
6261
if (!state || !storedState || state !== storedState) {
6362
return reply.status(400).send({ error: 'Invalid or missing OAuth state — possible CSRF attack' });
6463
}
@@ -183,7 +182,8 @@ export async function authRoutes(app: FastifyInstance) {
183182
// Google callback
184183
app.get('/google/callback', async (request: FastifyRequest<{ Querystring: OAuthCallbackQuery }>, reply: FastifyReply) => {
185184
const { code, state } = request.query;
186-
const storedState = (request.cookies as any)?.oauth_state;
185+
186+
const storedState = request.cookies?.oauth_state;
187187
if (!state || !storedState || state !== storedState) {
188188
return reply.status(400).send({ error: 'Invalid or missing OAuth state — possible CSRF attack' });
189189
}

apps/backend/src/routes/nfc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export async function nfcRoutes(app: FastifyInstance) {
100100
}
101101

102102
const safeUsername = encodeURIComponent(username);
103-
const payloadUrl = `https://dev-card.vercel.app/${safeUsername}${
103+
const payloadUrl = `${process.env.PUBLIC_APP_URL}/${safeUsername}${
104104
cardId ? `?card=${encodeURIComponent(cardId)}` : ''
105105
}`;
106106
const response: NfcPayloadResponse = {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import '@fastify/cookie';
2+
import { FastifyRequest } from 'fastify';
3+
4+
declare module 'fastify' {
5+
interface FastifyRequest {
6+
cookies: Record<string, string | undefined>;
7+
}
8+
}

apps/mobile/App.tsx

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,50 @@
11
import React from 'react';
2-
import { NavigationContainer } from '@react-navigation/native';
2+
import { NavigationContainer, LinkingOptions } from '@react-navigation/native';
33
import { SafeAreaProvider } from 'react-native-safe-area-context';
44
import { GestureHandlerRootView } from 'react-native-gesture-handler';
55
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
66
import { AuthProvider, useAuth } from './src/context/AuthContext';
77
import { ThemeProvider } from './src/context/ThemeContext';
88
import AuthStack from './src/navigation/AuthStack';
99
import MainTabs from './src/navigation/MainTabs';
10+
import SplashScreen from './src/screens/SplashScreen';
11+
import { DEEP_LINK_SCHEME } from './src/config';
1012

1113
import { Linking, StyleSheet } from 'react-native';
1214

15+
// ── Deep Link Configuration ───────────────────────────────────────────────────
16+
17+
const linking: LinkingOptions<{}> = {
18+
prefixes: [`${DEEP_LINK_SCHEME}://`],
19+
config: {
20+
screens: {
21+
MainTabs: {
22+
screens: {
23+
Home: 'home',
24+
Scan: 'scan',
25+
},
26+
},
27+
DevCardView: 'u/:username',
28+
},
29+
},
30+
};
31+
32+
// ── App Content ───────────────────────────────────────────────────────────────
33+
1334
function AppContent() {
1435
const { isAuthenticated, isLoading, login } = useAuth();
1536

1637
React.useEffect(() => {
1738
const handleDeepLink = (event: { url: string }) => {
18-
console.log('--- DEEP LINK RECEIVED ---');
19-
console.log('URL:', event.url);
20-
const url = new URL(event.url);
21-
const hashParams = new URLSearchParams(url.hash.replace(/^#/, ''));
22-
const token = url.searchParams.get('token') || hashParams.get('token');
23-
if (token) {
24-
console.log('Token found, logging in...');
25-
login(token);
39+
try {
40+
const url = new URL(event.url);
41+
const hashParams = new URLSearchParams(url.hash.replace(/^#/, ''));
42+
const token = url.searchParams.get('token') || hashParams.get('token');
43+
if (token) {
44+
login(token);
45+
}
46+
} catch (error) {
47+
console.error('Deep link parse error:', error);
2648
}
2749
};
2850

@@ -38,16 +60,18 @@ function AppContent() {
3860
}, [login]);
3961

4062
if (isLoading) {
41-
return null; // Splash screen could go here
63+
return <SplashScreen />;
4264
}
4365

4466
return (
45-
<NavigationContainer>
67+
<NavigationContainer linking={linking}>
4668
{isAuthenticated ? <MainTabs /> : <AuthStack />}
4769
</NavigationContainer>
4870
);
4971
}
5072

73+
// ── Root ───────────────────────────────────────────────────────────────────────
74+
5175
export default function App() {
5276
return (
5377
<GestureHandlerRootView style={styles.gestureRoot}>

apps/mobile/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'react-native-gesture-handler';
2-
import { registerRootComponent } from 'expo';
2+
import { AppRegistry } from 'react-native';
33
import App from './App';
4+
import { name as appName } from './app.json';
45

5-
// registerRootComponent handles mounting and bootstrapping the app
6-
// on both native mobile devices (Expo Go) and web browsers seamlessly.
7-
registerRootComponent(App);
6+
AppRegistry.registerComponent(appName, () => App);

0 commit comments

Comments
 (0)