Skip to content

Commit 53a2626

Browse files
committed
feat(auth): add GitHub OAuth login functionality
- Implemented GitHub OAuth login and signup options in the Login and Register views. - Added localization support for GitHub OAuth messages in auth.ts. - Removed deprecated login.ts localization file. - Created a new backend route to check GitHub OAuth status. - Added unit tests for the GitHub status route. - Introduced GitHubIcon component for UI representation.
1 parent 20a2aed commit 53a2626

File tree

15 files changed

+1118
-179
lines changed

15 files changed

+1118
-179
lines changed

services/backend/api-spec.json

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8963,7 +8963,7 @@
89638963
}
89648964
},
89658965
"403": {
8966-
"description": "Forbidden - Login is disabled by administrator",
8966+
"description": "Forbidden - Login is disabled by administrator or GitHub OAuth is disabled",
89678967
"content": {
89688968
"application/json": {
89698969
"schema": {
@@ -8978,7 +8978,7 @@
89788978
"error"
89798979
],
89808980
"additionalProperties": false,
8981-
"description": "Forbidden - Login is disabled by administrator"
8981+
"description": "Forbidden - Login is disabled by administrator or GitHub OAuth is disabled"
89828982
}
89838983
}
89848984
}
@@ -9156,6 +9156,64 @@
91569156
}
91579157
}
91589158
},
9159+
"/api/auth/github/status": {
9160+
"get": {
9161+
"summary": "Check GitHub OAuth status",
9162+
"tags": [
9163+
"Authentication"
9164+
],
9165+
"description": "Returns whether GitHub OAuth is enabled and configured. This endpoint can be used by the frontend to determine whether to show the \"Login with GitHub\" button.",
9166+
"responses": {
9167+
"200": {
9168+
"description": "GitHub OAuth status information",
9169+
"content": {
9170+
"application/json": {
9171+
"schema": {
9172+
"type": "object",
9173+
"properties": {
9174+
"enabled": {
9175+
"type": "boolean",
9176+
"description": "Whether GitHub OAuth is enabled and properly configured"
9177+
},
9178+
"configured": {
9179+
"type": "boolean",
9180+
"description": "Whether GitHub OAuth settings are present (regardless of enabled status)"
9181+
}
9182+
},
9183+
"required": [
9184+
"enabled",
9185+
"configured"
9186+
],
9187+
"additionalProperties": false,
9188+
"description": "GitHub OAuth status information"
9189+
}
9190+
}
9191+
}
9192+
},
9193+
"500": {
9194+
"description": "Internal Server Error",
9195+
"content": {
9196+
"application/json": {
9197+
"schema": {
9198+
"type": "object",
9199+
"properties": {
9200+
"error": {
9201+
"type": "string",
9202+
"description": "Error message"
9203+
}
9204+
},
9205+
"required": [
9206+
"error"
9207+
],
9208+
"additionalProperties": false,
9209+
"description": "Internal Server Error"
9210+
}
9211+
}
9212+
}
9213+
}
9214+
}
9215+
}
9216+
},
91599217
"/api/auth/logout": {
91609218
"post": {
91619219
"summary": "User logout",

services/backend/api-spec.yaml

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6279,7 +6279,8 @@ paths:
62796279
additionalProperties: false
62806280
description: Redirect to GitHub OAuth authorization URL
62816281
"403":
6282-
description: Forbidden - Login is disabled by administrator
6282+
description: Forbidden - Login is disabled by administrator or GitHub OAuth is
6283+
disabled
62836284
content:
62846285
application/json:
62856286
schema:
@@ -6291,7 +6292,8 @@ paths:
62916292
required:
62926293
- error
62936294
additionalProperties: false
6294-
description: Forbidden - Login is disabled by administrator
6295+
description: Forbidden - Login is disabled by administrator or GitHub OAuth is
6296+
disabled
62956297
"500":
62966298
description: Internal Server Error
62976299
content:
@@ -6410,6 +6412,48 @@ paths:
64106412
- error
64116413
additionalProperties: false
64126414
description: Internal Server Error
6415+
/api/auth/github/status:
6416+
get:
6417+
summary: Check GitHub OAuth status
6418+
tags:
6419+
- Authentication
6420+
description: Returns whether GitHub OAuth is enabled and configured. This
6421+
endpoint can be used by the frontend to determine whether to show the
6422+
"Login with GitHub" button.
6423+
responses:
6424+
"200":
6425+
description: GitHub OAuth status information
6426+
content:
6427+
application/json:
6428+
schema:
6429+
type: object
6430+
properties:
6431+
enabled:
6432+
type: boolean
6433+
description: Whether GitHub OAuth is enabled and properly configured
6434+
configured:
6435+
type: boolean
6436+
description: Whether GitHub OAuth settings are present (regardless of enabled
6437+
status)
6438+
required:
6439+
- enabled
6440+
- configured
6441+
additionalProperties: false
6442+
description: GitHub OAuth status information
6443+
"500":
6444+
description: Internal Server Error
6445+
content:
6446+
application/json:
6447+
schema:
6448+
type: object
6449+
properties:
6450+
error:
6451+
type: string
6452+
description: Error message
6453+
required:
6454+
- error
6455+
additionalProperties: false
6456+
description: Internal Server Error
64136457
/api/auth/logout:
64146458
post:
64156459
summary: User logout

services/backend/src/global-settings/github-oauth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const githubOAuthSettings: GlobalSettingsModule = {
4545
key: 'github.oauth.scope',
4646
defaultValue: 'user:email',
4747
type: 'string',
48-
description: 'GitHub OAuth requested scopes',
48+
description: 'GitHub OAuth requested scopes (user:email is required for email access)',
4949
encrypted: false,
5050
required: false
5151
}

services/backend/src/lib/lucia.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ function initializeLucia(): Lucia {
5454
}
5555

5656
// Create Lucia adapter with existing database instance
57+
// Note: DrizzleSQLiteAdapter expects (db, sessionTable, userTable)
5758
const adapter = new DrizzleSQLiteAdapter(
5859
db,
5960
authSessionTable,
@@ -97,11 +98,25 @@ function initializeLucia(): Lucia {
9798
}
9899

99100
// Lazy initialization function for GitHub OAuth
100-
function initializeGithubAuth(): GitHub {
101+
async function initializeGithubAuth(): Promise<GitHub> {
102+
// Import GlobalSettingsInitService to get GitHub OAuth configuration
103+
const { GlobalSettingsInitService } = await import('../global-settings');
104+
const githubConfig = await GlobalSettingsInitService.getGitHubOAuthConfiguration();
105+
106+
if (!githubConfig) {
107+
// Return a dummy GitHub instance if not configured
108+
// This prevents errors but the actual OAuth routes will handle the validation
109+
return new GitHub(
110+
'not_configured',
111+
'not_configured',
112+
'http://localhost:3000/api/auth/github/callback'
113+
);
114+
}
115+
101116
return new GitHub(
102-
process.env.GITHUB_CLIENT_ID || 'YOUR_GITHUB_CLIENT_ID_HERE', // Replace with your actual Client ID or load from env
103-
process.env.GITHUB_CLIENT_SECRET || 'YOUR_GITHUB_CLIENT_SECRET_HERE', // Replace with your actual Client Secret or load from env
104-
process.env.GITHUB_REDIRECT_URI || 'http://localhost:3000/api/auth/github/callback'
117+
githubConfig.clientId,
118+
githubConfig.clientSecret,
119+
githubConfig.callbackUrl
105120
);
106121
}
107122

@@ -132,15 +147,16 @@ if (process.env.NODE_ENV !== 'production') {
132147
resetLucia();
133148

134149
// Getter function for GitHub OAuth instance
135-
export function getGithubAuth(): GitHub {
150+
export async function getGithubAuth(): Promise<GitHub> {
136151
if (!githubAuthInstance) {
137-
githubAuthInstance = initializeGithubAuth();
152+
githubAuthInstance = await initializeGithubAuth();
138153
}
139154
return githubAuthInstance;
140155
}
141156

142157
// Legacy exports for backward compatibility (deprecated)
143158
export const lucia = getLucia;
159+
// Note: githubAuth is now async, so legacy usage may need updating
144160
export const githubAuth = getGithubAuth;
145161

146162
// IMPORTANT: Define DatabaseUserAttributes and DatabaseSessionAttributes

0 commit comments

Comments
 (0)