From 119b15fae7a1ea60c01c6347501e12ae1dd34d36 Mon Sep 17 00:00:00 2001 From: kristiankrafcik Date: Sat, 12 Oct 2024 11:08:54 +0000 Subject: [PATCH 1/5] #github-username create internal User type with github username property, create lit task, handle error after fetching --- .../static/js/components/webstatus-login.ts | 12 +-- .../js/contexts/firebase-user-context.ts | 8 +- .../webstatus-firebase-auth-service.ts | 80 +++++++++++++++++-- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/frontend/src/static/js/components/webstatus-login.ts b/frontend/src/static/js/components/webstatus-login.ts index 980fa2d3..0439a504 100644 --- a/frontend/src/static/js/components/webstatus-login.ts +++ b/frontend/src/static/js/components/webstatus-login.ts @@ -18,8 +18,10 @@ import {consume} from '@lit/context'; import {LitElement, type TemplateResult, html, nothing} from 'lit'; import {customElement, state} from 'lit/decorators.js'; -import {User} from 'firebase/auth'; -import {firebaseUserContext} from '../contexts/firebase-user-context.js'; +import { + FirebaseUser, + firebaseUserContext, +} from '../contexts/firebase-user-context.js'; import { AuthConfig, firebaseAuthContext, @@ -34,7 +36,7 @@ export class WebstatusLogin extends LitElement { @consume({context: firebaseUserContext, subscribe: true}) @state() - user?: User; + user?: FirebaseUser; handleLogInClick(authConfig: AuthConfig) { if (this.user === undefined) { @@ -72,14 +74,14 @@ export class WebstatusLogin extends LitElement { } renderAuthenticatedButton( - user: User, + user: FirebaseUser, authConfig: AuthConfig ): TemplateResult { return html` ${user.email}${user?.gitHubUsername || user.email} this.handleLogOutClick(authConfig)} diff --git a/frontend/src/static/js/contexts/firebase-user-context.ts b/frontend/src/static/js/contexts/firebase-user-context.ts index 053a3d4f..2ef4c298 100644 --- a/frontend/src/static/js/contexts/firebase-user-context.ts +++ b/frontend/src/static/js/contexts/firebase-user-context.ts @@ -19,6 +19,12 @@ import {createContext} from '@lit/context'; import type {User} from 'firebase/auth'; export type {User} from 'firebase/auth'; -export const firebaseUserContext = createContext( +export const firebaseUserContext = createContext( 'firebase-user' ); + +type FirebaseUser = User & { + gitHubUsername: string | null; +}; + +export type {FirebaseUser}; diff --git a/frontend/src/static/js/services/webstatus-firebase-auth-service.ts b/frontend/src/static/js/services/webstatus-firebase-auth-service.ts index a0d223e8..8a27484c 100644 --- a/frontend/src/static/js/services/webstatus-firebase-auth-service.ts +++ b/frontend/src/static/js/services/webstatus-firebase-auth-service.ts @@ -16,6 +16,7 @@ import {customElement, property, state} from 'lit/decorators.js'; import {consume, provide} from '@lit/context'; +import {Task} from '@lit/task'; import { FirebaseApp, firebaseAppContext, @@ -31,14 +32,19 @@ import { getAuth, signInWithPopup, } from 'firebase/auth'; -import {User, firebaseUserContext} from '../contexts/firebase-user-context.js'; +import { + User, + FirebaseUser, + firebaseUserContext, +} from '../contexts/firebase-user-context.js'; import {ServiceElement} from './service-element.js'; - interface FirebaseAuthSettings { emulatorURL: string; tenantID: string; } +const GITHUB_USERNAME_REQUEST_URL: string = 'https://api.github.com/user/'; + @customElement('webstatus-firebase-auth-service') export class WebstatusFirebaseAuthService extends ServiceElement { @property({type: Object}) @@ -52,7 +58,9 @@ export class WebstatusFirebaseAuthService extends ServiceElement { firebaseAuthConfig?: AuthConfig; @provide({context: firebaseUserContext}) - user?: User; + user?: FirebaseUser; + + _loadingGithubUsername?: Task; // Useful for testing authInitializer: (app: FirebaseApp | undefined) => Auth = getAuth; @@ -60,6 +68,31 @@ export class WebstatusFirebaseAuthService extends ServiceElement { // Useful for testing emulatorConnector: (auth: Auth, url: string) => void = connectAuthEmulator; + handleGithubUsernameError(res: Response, email: string) { + const err = new Error(); + if (res.status === 403 && res.headers.get('X-RateLimit-Remaining') == '0') { + const resetsAtMS = Number(`${res.headers.get('X-RateLimit-Reset')}000`); + err.message = `Status: ${res.status}, Rate limit exceeded, try again in ${Math.ceil((resetsAtMS - Date.now()) / 60000)}m`; + } else if (res.status === 404) { + err.message = `Status: ${res.status}, Could not find user data for github: ${email}`; + } else { + // add other cases if you want to handle them + err.message = `Unexpected status code: ${res.status}`; + } + throw err; + } + + async getGithubUser(token: string): Promise { + return fetch(`${GITHUB_USERNAME_REQUEST_URL}`, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + Accept: 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + }, + }); + } + initFirebaseAuth() { if (this.firebaseApp) { const auth = this.authInitializer(this.firebaseApp); @@ -84,8 +117,45 @@ export class WebstatusFirebaseAuthService extends ServiceElement { // Set up the callback that will detect when: // 1. The user first logs in // 2. Resuming a session - this.firebaseAuthConfig.auth.onAuthStateChanged(user => { - this.user = user ? user : undefined; + this.firebaseAuthConfig.auth.onAuthStateChanged((user: User | null) => { + if (user !== null) { + this.user = + user !== null ? {...user, gitHubUsername: 'empty'} : undefined; + this._loadingGithubUsername = new Task(this, { + args: (): [any] => [this.user], + task: async ([firebaseUser]: [any]) => { + try { + if ( + firebaseUser && + typeof firebaseUser !== 'string' && + firebaseUser.accessToken + ) { + const res: Response = await this.getGithubUser( + firebaseUser.accessToken + ); + if (res.ok) { + const data = await res.json(); + if (this.user !== undefined) { + this.user = { + ...this.user, + gitHubUsername: data.login, + }; + } + } else { + this.handleGithubUsernameError(res, this.user?.email || ''); + } + } else { + throw new Error('Github username request failed.'); + } + } catch (e: any) { + console.error(e.message); + } + }, + }); + this._loadingGithubUsername.run(); + } else { + throw new Error('Github username request failed.'); + } }); } } From 941d7160f696e38863e48b3c1276d074c208be20 Mon Sep 17 00:00:00 2001 From: kristiankrafcik Date: Sun, 20 Oct 2024 17:56:19 +0000 Subject: [PATCH 2/5] #github-username add octokit to frontend, implement octokit call for github username --- .../webstatus-firebase-auth-service.ts | 88 +++++-------------- 1 file changed, 22 insertions(+), 66 deletions(-) diff --git a/frontend/src/static/js/services/webstatus-firebase-auth-service.ts b/frontend/src/static/js/services/webstatus-firebase-auth-service.ts index 8a27484c..1affccf3 100644 --- a/frontend/src/static/js/services/webstatus-firebase-auth-service.ts +++ b/frontend/src/static/js/services/webstatus-firebase-auth-service.ts @@ -33,18 +33,16 @@ import { signInWithPopup, } from 'firebase/auth'; import { - User, FirebaseUser, firebaseUserContext, } from '../contexts/firebase-user-context.js'; import {ServiceElement} from './service-element.js'; +import {Octokit} from '@octokit/rest'; interface FirebaseAuthSettings { emulatorURL: string; tenantID: string; } -const GITHUB_USERNAME_REQUEST_URL: string = 'https://api.github.com/user/'; - @customElement('webstatus-firebase-auth-service') export class WebstatusFirebaseAuthService extends ServiceElement { @property({type: Object}) @@ -68,30 +66,10 @@ export class WebstatusFirebaseAuthService extends ServiceElement { // Useful for testing emulatorConnector: (auth: Auth, url: string) => void = connectAuthEmulator; - handleGithubUsernameError(res: Response, email: string) { - const err = new Error(); - if (res.status === 403 && res.headers.get('X-RateLimit-Remaining') == '0') { - const resetsAtMS = Number(`${res.headers.get('X-RateLimit-Reset')}000`); - err.message = `Status: ${res.status}, Rate limit exceeded, try again in ${Math.ceil((resetsAtMS - Date.now()) / 60000)}m`; - } else if (res.status === 404) { - err.message = `Status: ${res.status}, Could not find user data for github: ${email}`; - } else { - // add other cases if you want to handle them - err.message = `Unexpected status code: ${res.status}`; - } - throw err; - } - - async getGithubUser(token: string): Promise { - return fetch(`${GITHUB_USERNAME_REQUEST_URL}`, { - method: 'GET', - headers: { - Authorization: `Bearer ${token}`, - Accept: 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28', - }, - }); - } + loadGithubUsername = async (token?: string) => { + const octokit = new Octokit({auth: token}); + return await octokit.users.getAuthenticated(); + }; initFirebaseAuth() { if (this.firebaseApp) { @@ -117,46 +95,24 @@ export class WebstatusFirebaseAuthService extends ServiceElement { // Set up the callback that will detect when: // 1. The user first logs in // 2. Resuming a session - this.firebaseAuthConfig.auth.onAuthStateChanged((user: User | null) => { - if (user !== null) { - this.user = - user !== null ? {...user, gitHubUsername: 'empty'} : undefined; - this._loadingGithubUsername = new Task(this, { - args: (): [any] => [this.user], - task: async ([firebaseUser]: [any]) => { - try { - if ( - firebaseUser && - typeof firebaseUser !== 'string' && - firebaseUser.accessToken - ) { - const res: Response = await this.getGithubUser( - firebaseUser.accessToken - ); - if (res.ok) { - const data = await res.json(); - if (this.user !== undefined) { - this.user = { - ...this.user, - gitHubUsername: data.login, - }; - } - } else { - this.handleGithubUsernameError(res, this.user?.email || ''); - } - } else { - throw new Error('Github username request failed.'); - } - } catch (e: any) { - console.error(e.message); - } - }, - }); - this._loadingGithubUsername.run(); - } else { - throw new Error('Github username request failed.'); + this.firebaseAuthConfig.auth.onAuthStateChanged( + async (authenticatedUser?: any) => { + if (authenticatedUser !== null) { + await this.loadGithubUsername(authenticatedUser.accessToken) + .then(githubUser => { + this.user = { + ...authenticatedUser, + gitHubUsername: githubUser.data.login || null, + }; + }) + .catch(_ => { + throw new Error('Github username request failed.'); + }); + } else { + throw new Error('No user authenticated.'); + } } - }); + ); } } From eddd361b8ae88b200ff35565219b5dce53464feb Mon Sep 17 00:00:00 2001 From: kristiankrafcik Date: Sun, 20 Oct 2024 17:57:10 +0000 Subject: [PATCH 3/5] #github-username add package jsons --- frontend/package.json | 2 + package-lock.json | 426 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 428 insertions(+) diff --git a/frontend/package.json b/frontend/package.json index 11bd5f49..918d24ab 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -64,11 +64,13 @@ "dependencies": { "@lit/context": "^1.1.0", "@lit/task": "^1.0.0", + "@octokit/rest": "^21.0.2", "@shoelace-style/shoelace": "^2.17.1", "@types/google.visualization": "^0.0.74", "@vaadin/router": "^1.7.5", "firebase": "^10.12.5", "lit": "^3.2.0", + "octokit": "^4.0.2", "openapi-fetch": "^0.12.0" } } diff --git a/package-lock.json b/package-lock.json index 398d631e..2cae79b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,11 +31,13 @@ "dependencies": { "@lit/context": "^1.1.0", "@lit/task": "^1.0.0", + "@octokit/rest": "^21.0.2", "@shoelace-style/shoelace": "^2.17.1", "@types/google.visualization": "^0.0.74", "@vaadin/router": "^1.7.5", "firebase": "^10.12.5", "lit": "^3.2.0", + "octokit": "^4.0.2", "openapi-fetch": "^0.12.0" }, "devDependencies": { @@ -1406,6 +1408,379 @@ "node": ">= 8" } }, + "node_modules/@octokit/app": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/@octokit/app/-/app-15.1.0.tgz", + "integrity": "sha512-TkBr7QgOmE6ORxvIAhDbZsqPkF7RSqTY4pLTtUQCvr6dTXqvi2fFo46q3h1lxlk/sGMQjqyZ0kEahkD/NyzOHg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-app": "^7.0.0", + "@octokit/auth-unauthenticated": "^6.0.0", + "@octokit/core": "^6.1.2", + "@octokit/oauth-app": "^7.0.0", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/types": "^13.0.0", + "@octokit/webhooks": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.1.tgz", + "integrity": "sha512-kRAd6yelV9OgvlEJE88H0VLlQdZcag9UlLr7dV0YYP37X8PPDvhgiTy66QVhDXdyoT0AleFN2w/qXkPdrSzINg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^8.1.0", + "@octokit/auth-oauth-user": "^5.1.0", + "@octokit/request": "^9.1.1", + "@octokit/request-error": "^6.1.1", + "@octokit/types": "^13.4.1", + "lru-cache": "^10.0.0", + "universal-github-app-jwt": "^2.2.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.1.tgz", + "integrity": "sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^7.0.0", + "@octokit/auth-oauth-user": "^5.0.1", + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.1.tgz", + "integrity": "sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-methods": "^5.0.0", + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.1.tgz", + "integrity": "sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^7.0.1", + "@octokit/oauth-methods": "^5.0.0", + "@octokit/request": "^9.0.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-unauthenticated": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.0.tgz", + "integrity": "sha512-zPSmfrUAcspZH/lOFQnVnvjQZsIvmfApQH6GzJrkIunDooU1Su2qt2FfMTSVPRp7WLTQyC20Kd55lF+mIYaohQ==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-app": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-7.1.3.tgz", + "integrity": "sha512-EHXbOpBkSGVVGF1W+NLMmsnSsJRkcrnVmDKt0TQYRBb6xWfWzoi9sBD4DIqZ8jGhOWO/V8t4fqFyJ4vDQDn9bg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^8.0.0", + "@octokit/auth-oauth-user": "^5.0.1", + "@octokit/auth-unauthenticated": "^6.0.0-beta.1", + "@octokit/core": "^6.0.0", + "@octokit/oauth-authorization-url": "^7.0.0", + "@octokit/oauth-methods": "^5.0.0", + "@types/aws-lambda": "^8.10.83", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz", + "integrity": "sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.2.tgz", + "integrity": "sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-authorization-url": "^7.0.0", + "@octokit/request": "^9.1.0", + "@octokit/request-error": "^6.1.0", + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "license": "MIT" + }, + "node_modules/@octokit/openapi-webhooks-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz", + "integrity": "sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-graphql": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.4.tgz", + "integrity": "sha512-pLZES1jWaOynXKHOqdnwZ5ULeVR6tVVCMm+AUbp0htdcyXDU95WbkYdU4R2ej1wKj5Tu94Mee2Ne0PjPO9cCyA==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz", + "integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.2.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.6.tgz", + "integrity": "sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.2.tgz", + "integrity": "sha512-XOWnPpH2kJ5VTwozsxGurw+svB2e61aWlmk5EVIYZPwFK5F9h4cyPyj9CIKRyMXMHSwpIsI3mPOdpMmrRhe7UQ==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^6.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.3.2.tgz", + "integrity": "sha512-FqpvcTpIWFpMMwIeSoypoJXysSAQ3R+ALJhXXSG1HTP3YZOIeLmcNcimKaXxTcws+Sh6yoRl13SJ5r8sXc1Fhw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^6.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", + "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.2.tgz", + "integrity": "sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.1.tgz", + "integrity": "sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@octokit/webhooks": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-13.3.0.tgz", + "integrity": "sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-webhooks-types": "8.3.0", + "@octokit/request-error": "^6.0.1", + "@octokit/webhooks-methods": "^5.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-methods": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-5.1.0.tgz", + "integrity": "sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, "node_modules/@open-wc/dedupe-mixin": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@open-wc/dedupe-mixin/-/dedupe-mixin-1.4.0.tgz", @@ -2055,6 +2430,12 @@ "@types/node": "*" } }, + "node_modules/@types/aws-lambda": { + "version": "8.10.145", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.145.tgz", + "integrity": "sha512-dtByW6WiFk5W5Jfgz1VM+YPA21xMXTuSFoLYIDY0L44jDLLflVPtZkYuu3/YxpGcvjzKFBZLU+GyKjR0HOYtyw==", + "license": "MIT" + }, "node_modules/@types/babel__code-frame": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/@types/babel__code-frame/-/babel__code-frame-7.0.6.tgz", @@ -3543,6 +3924,12 @@ "node": ">=10.0.0" } }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3555,6 +3942,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8900,6 +9293,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/octokit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/octokit/-/octokit-4.0.2.tgz", + "integrity": "sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg==", + "license": "MIT", + "dependencies": { + "@octokit/app": "^15.0.0", + "@octokit/core": "^6.0.0", + "@octokit/oauth-app": "^7.0.0", + "@octokit/plugin-paginate-graphql": "^5.0.0", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0", + "@octokit/plugin-retry": "^7.0.0", + "@octokit/plugin-throttling": "^9.0.0", + "@octokit/request-error": "^6.0.0", + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -12016,6 +12430,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/universal-github-app-jwt": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz", + "integrity": "sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ==", + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", From f2cf3b060951c5a56bc83082b401d08054167655 Mon Sep 17 00:00:00 2001 From: kristiankrafcik Date: Mon, 21 Oct 2024 17:05:21 +0000 Subject: [PATCH 4/5] #github-username package-lock.json --- package-lock.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b37a023..3709a66e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,11 +34,10 @@ "@octokit/rest": "^21.0.2", "@shoelace-style/shoelace": "^2.17.1", "@types/google.visualization": "^0.0.74", - "octokit": "^4.0.2", "@vaadin/router": "^2.0.0", "firebase": "^10.14.1", "lit": "^3.2.1", - + "octokit": "^4.0.2", "openapi-fetch": "^0.12.0" }, "devDependencies": { From c128cb4e14e62af9f5aed2d9951a2d4b13ad5576 Mon Sep 17 00:00:00 2001 From: kristiankrafcik Date: Mon, 4 Nov 2024 20:00:40 +0000 Subject: [PATCH 5/5] #github-username edit test, and webstatus-login displayed string --- e2e/tests/login.spec.ts | 27 ++++++++++++++----- .../static/js/components/webstatus-login.ts | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/e2e/tests/login.spec.ts b/e2e/tests/login.spec.ts index 269c10f3..246d2cca 100644 --- a/e2e/tests/login.spec.ts +++ b/e2e/tests/login.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {test, expect} from '@playwright/test'; +import {test, expect, request} from '@playwright/test'; test('matches the screenshot for unauthenticated user', async ({page}) => { await page.goto('http://localhost:5555/'); @@ -31,18 +31,31 @@ test('can sign in and sign out user', async ({page}) => { const popupPromise = page.waitForEvent('popup'); await page.goto('http://localhost:5555/'); await page.getByText('Log in').click(); + await page.route('*//api.github.com/*', async route => { + // Mock successful login response + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + email: 'test_email@gmail.com', + data: { + login: 'default_user', + }, + }), + }); + }); const popup = await popupPromise; - await popup.getByText('test user 1').waitFor(); - await popup.getByText('test user 1').hover(); // Needed for Firefox for some reason. - await popup.getByText('test user 1').click(); + await popup.getByText('default_user').waitFor(); + await popup.getByText('default_user').hover(); // Needed for Firefox for some reason. + await popup.getByText('default_user').click(); await popup.waitForEvent('close'); const login = page.locator('webstatus-login'); - const expectedEmail = 'test.user.1@example.com'; + const expectedUsername = 'default_user'; - // Should have the email address - await expect(login).toContainText(expectedEmail); + // Should have the githubUsername = 'default_user' + await expect(login).toContainText(expectedUsername); const header = page.locator('webstatus-header'); await expect(header).toHaveScreenshot('authenticated-header.png'); diff --git a/frontend/src/static/js/components/webstatus-login.ts b/frontend/src/static/js/components/webstatus-login.ts index 14bcb77a..8e4b91ac 100644 --- a/frontend/src/static/js/components/webstatus-login.ts +++ b/frontend/src/static/js/components/webstatus-login.ts @@ -81,7 +81,7 @@ export class WebstatusLogin extends LitElement { ${user?.gitHubUsername || user.email}${user?.gitHubUsername} this.handleLogOutClick(authConfig)}