🔒 Add Discord admin user permissions and update developer access check logic
This commit is contained in:
137
code/websites/pokedex.online/DISCORD_PERMISSIONS_SETUP.md
Normal file
137
code/websites/pokedex.online/DISCORD_PERMISSIONS_SETUP.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# Discord User Permissions Setup Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The app now checks Discord usernames/IDs to grant developer tool access. Users must be in the allowlist to access developer features.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### 1. Find Your Discord Username/ID
|
||||||
|
|
||||||
|
You can use any of the following to identify users:
|
||||||
|
|
||||||
|
- **Username**: Your current Discord username (e.g., `fragginwagon`)
|
||||||
|
- **Global Name**: Your display name (if different from username)
|
||||||
|
- **Discord ID**: Your numeric Discord ID (e.g., `123456789012345678`)
|
||||||
|
|
||||||
|
**How to Find Your Discord ID:**
|
||||||
|
1. Enable Developer Mode in Discord: Settings → Advanced → Developer Mode (ON)
|
||||||
|
2. Right-click your username anywhere → Copy User ID
|
||||||
|
3. Or use this Discord bot command: `/userinfo` or `!userinfo`
|
||||||
|
|
||||||
|
### 2. Configure Environment Variables
|
||||||
|
|
||||||
|
Add allowed users to your `.env` file:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Discord User Permissions
|
||||||
|
# Comma-separated list of Discord usernames, display names, or IDs
|
||||||
|
DISCORD_ADMIN_USERS=fragginwagon,AnotherUser,123456789012345678
|
||||||
|
```
|
||||||
|
|
||||||
|
**Multiple formats supported:**
|
||||||
|
```env
|
||||||
|
# Just usernames
|
||||||
|
DISCORD_ADMIN_USERS=fragginwagon,coolguy99
|
||||||
|
|
||||||
|
# Mix of usernames and IDs
|
||||||
|
DISCORD_ADMIN_USERS=fragginwagon,123456789012345678,coolguy99
|
||||||
|
|
||||||
|
# Using Discord IDs (most reliable)
|
||||||
|
DISCORD_ADMIN_USERS=123456789012345678,987654321098765432
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Location of Configuration
|
||||||
|
|
||||||
|
**Development (.env file):**
|
||||||
|
```bash
|
||||||
|
/Users/fragginwagon/Developer/MemoryPalace/code/websites/pokedex.online/server/.env
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production (Docker):**
|
||||||
|
Add to your `docker-compose.tmp.yml` or production environment:
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- DISCORD_ADMIN_USERS=fragginwagon,user2,123456789012345678
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in your server's `.env` file that gets loaded by Docker.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. User logs in with Discord OAuth
|
||||||
|
2. Backend fetches user info from Discord API
|
||||||
|
3. Backend checks if username, global name, OR Discord ID matches the allowlist
|
||||||
|
4. Backend returns `permissions: ['developer_tools.view']` if user is authorized
|
||||||
|
5. Frontend checks `hasDevAccess()` to show/hide developer tools
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Test if you're in the allowlist:
|
||||||
|
|
||||||
|
1. Add your Discord username to `DISCORD_ADMIN_USERS` in `.env`
|
||||||
|
2. Restart the backend server:
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.tmp.yml restart backend
|
||||||
|
```
|
||||||
|
3. Log in with Discord OAuth in the app
|
||||||
|
4. Open Developer Tools (should now be visible if authorized)
|
||||||
|
|
||||||
|
### Check backend logs:
|
||||||
|
|
||||||
|
Look for these messages:
|
||||||
|
```
|
||||||
|
✅ Discord user authenticated { username: 'fragginwagon', id: '123456789012345678' }
|
||||||
|
✅ Discord user granted developer access { username: 'fragginwagon' }
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if not authorized:
|
||||||
|
```
|
||||||
|
✅ Discord user authenticated { username: 'unauthorized', id: '999999999999999999' }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- **Case-insensitive matching**: Usernames are compared in lowercase
|
||||||
|
- **Multiple formats**: Supports username, display name, and Discord ID
|
||||||
|
- **Fallback behavior**: If Discord user info fetch fails, no permissions are granted (fail-safe)
|
||||||
|
- **No permissions stored client-side**: Permissions are checked on every OAuth login
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Developer tools not appearing after adding username:**
|
||||||
|
1. Check backend logs for "Discord user authenticated" message
|
||||||
|
2. Verify your username matches exactly (check for typos)
|
||||||
|
3. Try using your Discord ID instead of username (more reliable)
|
||||||
|
4. Ensure backend restarted after changing `.env`
|
||||||
|
|
||||||
|
**"Failed to fetch Discord user info" in logs:**
|
||||||
|
- OAuth token may not have `identify` scope
|
||||||
|
- Check Discord OAuth app settings
|
||||||
|
- Verify `VITE_DISCORD_CLIENT_ID` and `DISCORD_CLIENT_SECRET` are correct
|
||||||
|
|
||||||
|
## Example Configuration
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Development
|
||||||
|
NODE_ENV=development
|
||||||
|
PORT=3099
|
||||||
|
|
||||||
|
# Discord OAuth
|
||||||
|
VITE_DISCORD_CLIENT_ID=your_client_id_here
|
||||||
|
DISCORD_CLIENT_SECRET=your_client_secret_here
|
||||||
|
VITE_DISCORD_REDIRECT_URI=http://localhost:5173/oauth/callback
|
||||||
|
|
||||||
|
# Allowed Users (add your Discord username or ID)
|
||||||
|
DISCORD_ADMIN_USERS=fragginwagon,123456789012345678
|
||||||
|
```
|
||||||
|
|
||||||
|
## Permission Levels
|
||||||
|
|
||||||
|
Currently implemented:
|
||||||
|
- `developer_tools.view` - Access to developer tools panel and feature flags
|
||||||
|
|
||||||
|
Future permissions (not yet implemented):
|
||||||
|
- `admin` - Full admin access
|
||||||
|
- `gamemaster.edit` - Edit gamemaster data
|
||||||
|
- `tournaments.manage` - Manage tournaments
|
||||||
@@ -180,6 +180,13 @@ export function getConfig() {
|
|||||||
// Security
|
// Security
|
||||||
session: {
|
session: {
|
||||||
secret: process.env.SESSION_SECRET || 'dev-secret-change-in-production'
|
secret: process.env.SESSION_SECRET || 'dev-secret-change-in-production'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Discord User Permissions
|
||||||
|
discord: {
|
||||||
|
adminUsers: process.env.DISCORD_ADMIN_USERS
|
||||||
|
? process.env.DISCORD_ADMIN_USERS.split(',').map(u => u.trim().toLowerCase())
|
||||||
|
: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,20 +98,14 @@ export function useDiscordOAuth() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if user is allowed to access developer tools
|
* Check if user is allowed to access developer tools
|
||||||
* Compares Discord username against backend-managed allowlist
|
* Checks permissions returned from backend during OAuth
|
||||||
*
|
*
|
||||||
* @param {Object} userPermissions - User permissions object from backend
|
|
||||||
* @returns {boolean} True if user has developer access
|
* @returns {boolean} True if user has developer access
|
||||||
*/
|
*/
|
||||||
function hasDevAccess(userPermissions = {}) {
|
function hasDevAccess() {
|
||||||
// Check explicit permission
|
// Check if tokens include permissions
|
||||||
if (userPermissions?.includes?.('developer_tools.view')) {
|
const permissions = oauth.tokens.value?.permissions || [];
|
||||||
return true;
|
return permissions.includes('developer_tools.view');
|
||||||
}
|
|
||||||
|
|
||||||
// Backend could also return discord_username_allowlist
|
|
||||||
// This would be checked server-side, but frontend can cache it
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user