Skip to content
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

Feat: Chess Mobile App with authentication #347

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c7877e8
feat: add react native app
ofcljaved Apr 20, 2024
34780e2
fix: rename image
ofcljaved Apr 20, 2024
db1dd8a
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved Apr 21, 2024
448dd27
feat: add react native app
ofcljaved Apr 20, 2024
98166bb
fix: rename image
ofcljaved Apr 20, 2024
9813f9b
chore: enable android build
ofcljaved Apr 22, 2024
d04884c
merged
ofcljaved Apr 22, 2024
4991905
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved Apr 22, 2024
039835c
chore: setup auth context
ofcljaved Apr 25, 2024
2572864
chore: auth layout setup
Apr 25, 2024
a68b7e2
chore: layout setup
ofcljaved Apr 26, 2024
90d93c9
chore: test authentication
Apr 26, 2024
fa3f5d7
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved Apr 27, 2024
ffea4b5
chore: implement cookie based auth
ofcljaved Apr 29, 2024
81c3b6b
chore: animate splash screen
Apr 29, 2024
3deb958
chore: sign-in screen
ofcljaved May 1, 2024
a30749b
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved May 1, 2024
fb06eb6
Merge branch 'feat/mobile-app' of https://github.com/ofcljaved/chess …
ofcljaved May 1, 2024
13e1737
chore: add sign-in button
ofcljaved May 2, 2024
cec682c
chore: add home screen & auth
ofcljaved May 4, 2024
7c772b3
chore: implement signout and home screen layout
ofcljaved May 7, 2024
13f6340
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved May 7, 2024
b6e3c87
chore: recoil setup
ofcljaved May 9, 2024
04fd69d
test: optimize recoil
May 9, 2024
a1df09f
refactor: improve recoil management
ofcljaved May 10, 2024
2152c79
refactor: improved font scaling
ofcljaved May 11, 2024
0d52bc0
Merge branch 'code100x:main' into feat/mobile-app
ofcljaved May 13, 2024
8ef8042
feat: add socket and chess
ofcljaved May 14, 2024
a5dd5c8
chore: improve chessboard ui
ofcljaved May 15, 2024
f760238
chore: move chess piece
ofcljaved May 15, 2024
33eec31
chore: piece moves
ofcljaved May 17, 2024
5b0835a
refact: update socket and chess logic
ofcljaved May 18, 2024
bf2acb9
chore: both party can move now
ofcljaved May 20, 2024
26b5980
feat: show all possible moves
ofcljaved May 20, 2024
52264cc
chore: add recent move
ofcljaved May 21, 2024
23decca
refactor: move chess to recoil
ofcljaved May 22, 2024
b6ac860
chore: flip board
ofcljaved May 27, 2024
2770915
refactor: improve coordination logic
ofcljaved May 28, 2024
bc4a63d
chore: add timer logic
ofcljaved May 30, 2024
e21690e
chore: timer working
ofcljaved Jun 1, 2024
9b1a4d6
chore: move table and game end logic
ofcljaved Jun 2, 2024
806dcd2
fix: add github login callback
Jun 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,24 @@
"dependencies": {
"@repo/db": "*",
"@types/express-session": "^1.18.0",
"base-64": "^1.0.0",
"cookie-session": "^2.1.0",
"cors": "^2.8.5",
"express": "^4.19.2",
"express-session": "^1.18.0",
"express-useragent": "^1.0.15",
"jsonwebtoken": "^9.0.2",
"passport": "^0.7.0",
"passport-facebook": "^3.0.0",
"passport-github2": "^0.1.12",
"passport-google-oauth20": "^2.0.0"
},
"devDependencies": {
"@types/base-64": "^1.0.2",
"@types/cookie-session": "^2.0.49",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/express-useragent": "^1.0.5",
"@types/jsonwebtoken": "^9.0.6",
"@types/passport": "^1.0.16"
}
Expand Down
30 changes: 27 additions & 3 deletions apps/backend/src/router/auth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Request, Response, Router } from 'express';
import passport from 'passport';
import jwt from 'jsonwebtoken';
import useragent from 'express-useragent';
import { db } from '../db';
import base64 from 'base-64';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use JWT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can Use JWT also, but it'll be two times longer than base64 encode token and also it needs a secret too.
Can shift to JWT there's no problem

const router = Router();

router.use(useragent.express());
const CLIENT_URL =
process.env.AUTH_REDIRECT_URL ?? 'http://localhost:5173/game/random';
const JWT_SECRET = process.env.JWT_SECRET || 'your_secret_key';
Expand All @@ -13,6 +15,7 @@ interface User {
}

router.get('/refresh', async (req: Request, res: Response) => {
console.log(req.headers.cookie);
if (req.user) {
const user = req.user as User;

Expand Down Expand Up @@ -60,11 +63,29 @@ router.get(
router.get(
'/google/callback',
passport.authenticate('google', {
successRedirect: CLIENT_URL,
// successRedirect: CLIENT_URL,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we only comment this here and not on github or facebook too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only tested for google, I'll update it after testing for github and facebook

failureRedirect: '/login/failed',
}),
(req, res) => {
res.redirect('/auth/capture-mode');
},
);

router.get('/capture-mode', (req, res) => {
const cookies = req.headers.cookie?.split(';').map((cookie) => cookie.trim());
const authCookie = cookies?.find((cookie) =>
cookie.startsWith('connect.sid'),
);
const token = base64.encode(authCookie!);
console.log('authCookie', token);

const ua = req.useragent;
if (ua?.isMobile) {
res.redirect(`chess-mobile://sign-in?cookie=${token}`);
} else {
res.redirect(CLIENT_URL);
}
});
router.get(
'/github',
passport.authenticate('github', { scope: ['read:user', 'user:email'] }),
Expand All @@ -73,9 +94,12 @@ router.get(
router.get(
'/github/callback',
passport.authenticate('github', {
successRedirect: CLIENT_URL,
// successRedirect: CLIENT_URL,
failureRedirect: '/login/failed',
}),
(req, res) => {
res.redirect('/auth/capture-mode');
},
);

router.get(
Expand Down
3 changes: 3 additions & 0 deletions apps/chess-mobile/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EXPO_USE_METRO_WORKSPACE_ROOT=1
EXPO_PUBLIC_API_URL=https://staging.example.com
EXPO_PUBLIC_WS_URL=ws://localhost:8080
24 changes: 24 additions & 0 deletions apps/chess-mobile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
node_modules/
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# expo router
expo-env.d.ts



ios
android

# macOS
.DS_Store

# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
102 changes: 102 additions & 0 deletions apps/chess-mobile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Chess Mobile App

**NOTE: This app has only been tested on Android devices.**

## Features

Demo Videos link:

- https://youtu.be/TYqO7j7ydDo
- https://youtu.be/-6WtZn5Zx0I
- https://youtube.com/shorts/uG1elnCFi4Q?feature=share

In the Mobile App, Users Can:

1. Sign up using Google or GitHub, similar to the web version.
2. Store cookies in secure storage and send them with every request for user authentication.
3. Play chess between mobile-to-mobile or mobile-to-desktop devices.
4. Note: "Play with Friend" and "Play as Guest" functionalities are currently not implemented.

## Tech Stack

1. Expo
2. Recoil for state management

## Running the App Locally

### Important Notes

- The app cannot be used with the `EXPO GO` mobile app due to authentication flow and deep-linking requirements.
- To pass the sign-in screen, a backend and WebSocket server must be running.

### Setup Instructions

1. **Backend and WebSocket Setup:**

- Mobile devices cannot access servers running on localhost. Instead, you must expose your backend and WebSocket server to the internet. A convenient way to do this is through [ngrok](https://ngrok.com/).
- Ngrok allows only one endpoint to be exposed for free. To expose both WebSocket and backend servers, you need a config file with your authToken.
- Ngrok also provides one free domain that doesn't change each time you start a server. Claim a free domain for the HTTP server to use the backend.

2. **Ngrok Configuration:**

- In order to edit the `ngrok.yml` file, run this command,
```bash
ngrok config edit
```
- Update the `ngrok.yml` file with the following content:
```yml
version: '2'
authtoken: YOUR_TOKEN_HERE
tunnels:
chess_server:
proto: http
addr: 3000
domain: dynamic-honeybee-humorous.ngrok-free.app
wschess:
proto: tcp
addr: 8080
```
(Replace `YOUR_TOKEN_HERE` with your actual Ngrok auth token.)
- Run the following command to start Ngrok:
```bash
ngrok start --all
```
(Ensure your backend is running on port 3000 and WebSocket on port 8080, adjust if necessary.)

3. **Environment Configuration:**

- Copy `.env.sample` to `.env`.
- Do not change the `EXPO_USE_METRO_WORKSPACE_ROOT` variable, as it is necessary for Expo metro config to work in a monorepo.
- Set the backend URL in `EXPO_PUBLIC_API_URL` and WebSocket URL in `EXPO_PUBLIC_WS_URL`.

4. **Running the App:**
```bash
# For Android
yarn expo run:android
# For iOS
yarn expo run:ios
```
_Note: Use Yarn as the package manager since it is a yarn turborepo._

### Troubleshooting

- **Android Development Build Issues:**
- Ensure you have an Android emulator and Java SDK that matches the emulator's requirements. Without this, the React Native app styles may flicker.
- Follow the setup guide [here](https://reactnative.dev/docs/set-up-your-environment).

## About the App

- Utilizes an animated splash screen via Lottie.
- Uses NativeWind for styling, bringing Tailwind CSS to mobile.
- Context is used for WebSocket to maintain consistent value with a single reference.
- Most data, including the chess object, is stored in Recoil.

## In Progress

- Implementing "Play with Friends" functionality.
- Adding WebSocket reconnect logic.
- Allowing users to join games via links.
- Implementing user cookie refresh to avoid repeated logins.
- Adding confetti effects (note: avoid using Lottie for this due to performance).
- Adding sound effects for moves.
- Creating a settings page for customizing color, theme, master volume, and avatar.
2 changes: 2 additions & 0 deletions apps/chess-mobile/app-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore
/// <reference types="nativewind/types" />
42 changes: 42 additions & 0 deletions apps/chess-mobile/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"expo": {
"name": "chess-mobile",
"slug": "chess-mobile",
"version": "1.0.0",
"scheme": "chess-mobile",
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/favicon.png"
},
"plugins": [
"expo-router",
"expo-secure-store"
],
"experiments": {
"typedRoutes": true,
"tsconfigPaths": true
},
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "dark",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#020617"
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"package": "com.codex100.chess"
}
}
}
Binary file added apps/chess-mobile/assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/chess-mobile/assets/chess.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/chess-mobile/assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/chess-mobile/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading