@@ -5,16 +5,64 @@ const App = (() => {
55
66 // Configuration
77 const CONFIG = {
8- CLIENT_ID : 'YOUR_GITHUB_CLIENT_ID ' ,
8+ CLIENT_ID : 'Iv23liYmAKkBpvhHAnQQ ' ,
99 API_BASE : 'https://api.github.com' ,
1010 STORAGE_KEY : 'github_token' ,
11+ COOKIE_KEY : 'github_pat' ,
1112 SEARCH_LIMIT : 100 ,
13+ OAUTH_REDIRECT_URI : window . location . origin + window . location . pathname ,
1214 } ;
1315
16+ // Cookie Functions
17+ function setCookie ( name , value , days ) {
18+ const expires = new Date ( ) ;
19+ expires . setTime ( expires . getTime ( ) + ( days * 24 * 60 * 60 * 1000 ) ) ;
20+ document . cookie = `${ name } =${ value } ;expires=${ expires . toUTCString ( ) } ;path=/;SameSite=Strict` ;
21+ }
22+
23+ function getCookie ( name ) {
24+ const nameEQ = name + "=" ;
25+ const ca = document . cookie . split ( ';' ) ;
26+ for ( let i = 0 ; i < ca . length ; i ++ ) {
27+ let c = ca [ i ] ;
28+ while ( c . charAt ( 0 ) === ' ' ) c = c . substring ( 1 , c . length ) ;
29+ if ( c . indexOf ( nameEQ ) === 0 ) return c . substring ( nameEQ . length , c . length ) ;
30+ }
31+ return null ;
32+ }
33+
34+ function deleteCookie ( name ) {
35+ document . cookie = `${ name } =;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;` ;
36+ }
37+
38+ function getStoredToken ( ) {
39+ // Check cookie first (for PAT)
40+ const cookieToken = getCookie ( CONFIG . COOKIE_KEY ) ;
41+ if ( cookieToken ) return cookieToken ;
42+
43+ // Fall back to localStorage (for OAuth)
44+ return localStorage . getItem ( CONFIG . STORAGE_KEY ) ;
45+ }
46+
47+ function storeToken ( token , useCookie = false ) {
48+ if ( useCookie ) {
49+ setCookie ( CONFIG . COOKIE_KEY , token , 365 ) ; // 1 year
50+ } else {
51+ localStorage . setItem ( CONFIG . STORAGE_KEY , token ) ;
52+ }
53+ state . accessToken = token ;
54+ }
55+
56+ function clearToken ( ) {
57+ localStorage . removeItem ( CONFIG . STORAGE_KEY ) ;
58+ deleteCookie ( CONFIG . COOKIE_KEY ) ;
59+ state . accessToken = null ;
60+ }
61+
1462 // State Management
1563 const state = {
1664 currentUser : null ,
17- accessToken : localStorage . getItem ( CONFIG . STORAGE_KEY ) ,
65+ accessToken : getStoredToken ( ) ,
1866 organizations : [ ] ,
1967 pullRequests : {
2068 incoming : [ ] ,
@@ -485,24 +533,76 @@ const App = (() => {
485533 } ;
486534
487535 // Auth Functions
488- const initiateLogin = ( ) => {
489- const token = prompt ( 'Please enter your GitHub Personal Access Token with repo scope:' ) ;
490- if ( token ) {
491- localStorage . setItem ( CONFIG . STORAGE_KEY , token ) ;
492- state . accessToken = token ;
493- window . location . reload ( ) ;
536+ const initiateOAuthLogin = ( ) => {
537+ const authUrl = `https://github.com/login/oauth/authorize?client_id=${ CONFIG . CLIENT_ID } &redirect_uri=${ encodeURIComponent ( CONFIG . OAUTH_REDIRECT_URI ) } &scope=repo%20read:org` ;
538+ window . location . href = authUrl ;
539+ } ;
540+
541+ const initiatePATLogin = ( ) => {
542+ show ( $ ( 'patModal' ) ) ;
543+ $ ( 'patInput' ) . focus ( ) ;
544+ } ;
545+
546+ const closePATModal = ( ) => {
547+ hide ( $ ( 'patModal' ) ) ;
548+ $ ( 'patInput' ) . value = '' ;
549+ } ;
550+
551+ const submitPAT = async ( ) => {
552+ const token = $ ( 'patInput' ) . value . trim ( ) ;
553+ if ( ! token ) {
554+ showToast ( 'Please enter a valid token' , 'error' ) ;
555+ return ;
556+ }
557+
558+ // Test the token
559+ try {
560+ const testResponse = await fetch ( `${ CONFIG . API_BASE } /user` , {
561+ headers : {
562+ 'Authorization' : `token ${ token } ` ,
563+ 'Accept' : 'application/vnd.github.v3+json'
564+ }
565+ } ) ;
566+
567+ if ( testResponse . ok ) {
568+ storeToken ( token , true ) ; // Store in cookie
569+ closePATModal ( ) ;
570+ window . location . reload ( ) ;
571+ } else {
572+ showToast ( 'Invalid token. Please check and try again.' , 'error' ) ;
573+ }
574+ } catch ( error ) {
575+ showToast ( 'Failed to validate token. Please try again.' , 'error' ) ;
494576 }
495577 } ;
496578
579+ const handleOAuthCallback = async ( ) => {
580+ const urlParams = new URLSearchParams ( window . location . search ) ;
581+ const code = urlParams . get ( 'code' ) ;
582+
583+ if ( code ) {
584+ // In a real implementation, you'd exchange this code for a token
585+ // via your backend server. For now, we'll show an error message.
586+ showToast ( 'OAuth authentication requires a backend server. Please use Personal Access Token instead.' , 'warning' ) ;
587+ // Clean up URL
588+ window . history . replaceState ( { } , document . title , window . location . pathname ) ;
589+ showLoginPrompt ( ) ;
590+ }
591+ } ;
592+
593+ const initiateLogin = ( ) => {
594+ // Legacy function - redirect to PAT login
595+ initiatePATLogin ( ) ;
596+ } ;
597+
497598 const handleAuthError = ( ) => {
498- localStorage . removeItem ( CONFIG . STORAGE_KEY ) ;
499- state . accessToken = null ;
599+ clearToken ( ) ;
500600 showLoginPrompt ( ) ;
501601 showToast ( 'Authentication failed. Please login again.' , 'error' ) ;
502602 } ;
503603
504604 const logout = ( ) => {
505- localStorage . removeItem ( CONFIG . STORAGE_KEY ) ;
605+ clearToken ( ) ;
506606 window . location . href = window . location . pathname ;
507607 } ;
508608
@@ -587,8 +687,24 @@ const App = (() => {
587687 }
588688 if ( loginBtn ) loginBtn . addEventListener ( 'click' , initiateLogin ) ;
589689
690+ // Add event listener for PAT input Enter key
691+ const patInput = $ ( 'patInput' ) ;
692+ if ( patInput ) {
693+ patInput . addEventListener ( 'keypress' , ( e ) => {
694+ if ( e . key === 'Enter' ) {
695+ submitPAT ( ) ;
696+ }
697+ } ) ;
698+ }
699+
590700 document . addEventListener ( 'keydown' , handleKeyboardShortcuts ) ;
591701
702+ // Check for OAuth callback
703+ if ( urlParams . get ( 'code' ) ) {
704+ handleOAuthCallback ( ) ;
705+ return ;
706+ }
707+
592708 // Check for demo mode
593709 if ( demo === 'true' ) {
594710 initializeDemoMode ( ) ;
@@ -619,7 +735,11 @@ const App = (() => {
619735 return {
620736 init,
621737 logout,
622- initiateLogin : ( ) => window . initiateLogin = initiateLogin
738+ initiateLogin : ( ) => window . initiateLogin = initiateLogin ,
739+ initiateOAuthLogin,
740+ initiatePATLogin,
741+ closePATModal,
742+ submitPAT
623743 } ;
624744} ) ( ) ;
625745
0 commit comments