Skip to content

Commit

Permalink
Merge pull request #397 from viktor44/hotfix/google_account_403
Browse files Browse the repository at this point in the history
Google account imrovements
  • Loading branch information
viktor44 authored Jul 9, 2024
2 parents 69bf008 + 684ecef commit bff44c6
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 25 deletions.
82 changes: 82 additions & 0 deletions .github/workflows/release-candidate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Release Candidate
on:
push:
tags:
- 'v*-b*'

jobs:
Linux:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: "18"
cache: "yarn"
# See https://github.com/nodejs/node-gyp/blob/main/docs/Force-npm-to-use-global-node-gyp.md
# https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md
# - name: Update node-gyp
# run: |
# npm install --global [email protected]
# npm config set node_gyp $(npm prefix -g)/lib/node_modules/node-gyp/bin/node-gyp.js
- name: Install dependencies
run: yarn install --immutable
- name: Build and Release
run: yarn release

MacOs:
runs-on: macos-13
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.CSC_LINK }}
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AC_TEAM_ID: ${{ secrets.AC_TEAM_ID }}
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: "18"
cache: "yarn"
- name: Configure Node
run: |
# npm v9 doesn't allow custom config parameters (i.e. node_gyp) anymode, so we have to downgrade it to v8
npm install -g npm@8
npm install -g node-gyp@latest
npm config set node_gyp $(npm prefix -g)/lib/node_modules/node-gyp/bin/node-gyp.js
- name: Install dependencies
run: yarn install --immutable
- name: Build and Release
run: yarn release

Windows:
runs-on: windows-2019
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.CSC_LINK }}
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: "18"
- name: Configure Node
shell: powershell
run: |
# npm v9 doesn't allow custom config parameters (i.e. node_gyp) anymode, so we have to downgrade it to v8
npm install -g npm@8
npm install -g node-gyp@latest
npm prefix -g | % {npm config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"}
- name: Install dependencies
run: yarn install --immutable
- name: Build and Release
run: yarn release
Binary file added .yarn/install-state.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "station-project",
"private": true,
"productName": "Station",
"version": "3.1.0-b1",
"version": "3.1.0-b3",
"description": "Station",
"homepage": "https://getstation.com",
"author": {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "station-desktop-app",
"productName": "Station",
"version": "3.1.0-b1",
"version": "3.1.0-b3",
"description": "Station",
"homepage": "https://getstation.com",
"author": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ export const JAVASCRIPT_INJECTIONS = {
gmail: ['gmailInjectedScript'],
slack: ['slackInjectedScript'],
'station-support': ['slackInjectedScript'],
'gdrive-mu': ['removeGoogleAccountInjectedScript'],
'gdrive-mu': ['removeGoogleAccountInjectedScript'],
'gcalendar-mu': ['removeGoogleAccountInjectedScript'],
'google-cloud': ['removeGoogleAccountInjectedScript'], //vk: FIXME: doesn't work
'google-keep': ['removeGoogleAccountInjectedScript'],
'meet': ['removeGoogleAccountInjectedScript'],
outlook: ['office365InjectedScript'],
'office-365': ['office365InjectedScript'],
'outlook-pro': ['office365InjectedScript'],
'google-keep': ['removeGoogleAccountInjectedScript'],
'facebook-messenger': ['messengerInjectedScript'],
'whatsapp': ['whatsappInjectedScript'],
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Schema$Person } from 'googleapis/build/src/apis/plus/v1';
import { people_v1 } from 'googleapis/build/src/apis/people/v1';
import { ServiceBase } from '../../lib/class';
import { service, timeout } from '../../lib/decorator';
import { RPC } from '../../lib/types';
import { Credentials } from 'google-auth-library/build/src/auth/credentials';
import { Credentials } from 'google-auth-library';

export type ElectronGoogleSignInResponse = {
tokens: Credentials,
profile: people_v1.Schema$Person,
}

@service('electron-google-oauth')
export class ElectronGoogleOAuthService extends ServiceBase implements RPC.Interface<ElectronGoogleOAuthService> {
@timeout(0)
// @ts-ignore
signIn(scopes: string[], forceAddSession?: boolean): Promise<{
tokens: Credentials,
profile: Schema$Person,
}> {}
signIn(scopes: string[], forceAddSession?: boolean): Promise<ElectronGoogleSignInResponse> {}
}
86 changes: 75 additions & 11 deletions packages/app/src/services/services/electron-google-oauth/main.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,95 @@
import { google } from 'googleapis';
import { people_v1 } from 'googleapis/build/src/apis/people/v1';
import { Credentials } from 'google-auth-library';
import ElectronGoogleOAuth2 from '@getstation/electron-google-oauth2';
import log from 'electron-log';

import { RPC } from '../../lib/types';
import { ElectronGoogleOAuthService } from './interface';
import { ElectronGoogleOAuthService, ElectronGoogleSignInResponse } from './interface';

const CLIENT_ID = process.env.GOOGLE_CLIENT_ID!;
const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET!;

export class ElectronGoogleOAuthServiceImpl extends ElectronGoogleOAuthService implements RPC.Interface<ElectronGoogleOAuthService> {
async signIn(scopes: string[], forceAddSession?: boolean) {
async signIn(scopes: string[], forceAddSession?: boolean): Promise<ElectronGoogleSignInResponse> {

const client = new ElectronGoogleOAuth2(CLIENT_ID, CLIENT_SECRET, scopes, { successRedirectURL: 'https://getstation.com/' });
return client.openAuthWindowAndGetTokens(forceAddSession)
.then(async (tokens) => {

const service = google.people({
try {
const service = google.people({
version: 'v1',
auth: client.oauth2Client,
});
});

const response = await service.people.get({
resourceName: 'people/me',
personFields: 'names,emailAddresses,photos',
sources: ['READ_SOURCE_TYPE_PROFILE'],
});
const response = await service.people.get({
resourceName: 'people/me',
personFields: 'names,emailAddresses,photos',
sources: ['READ_SOURCE_TYPE_PROFILE'],
});

return { tokens, profile: response.data as people_v1.Schema$Person };
return { tokens, profile: response.data as people_v1.Schema$Person };
}
catch (err) {
log.error(`Google profile request error ${err}`);
return this.parseToken(tokens);
}
});
}

private parseToken(tokens: Credentials): ElectronGoogleSignInResponse {
try {
//vk: id_token format https://developers.google.com/identity/gsi/web/reference/js-reference#credential
const decodedStr = Buffer.from(tokens.id_token!.split('.')[1], 'base64').toString()
const tokenPayload = JSON.parse(decodedStr);

return {
tokens,
profile: {
names: [
{
metadata: {
source: {
id: tokenPayload.sub,
}
},
displayName: tokenPayload.name,
givenName: tokenPayload.given_name,
familyName: tokenPayload.family_name,
}
],
emailAddresses: [
{
type: '',
value: tokenPayload.email,
}
],
photos: [
{
url: tokenPayload.picture,
}
]
}
};
}
catch (err) {
log.error(`Parse token error ${err}`);
return {
tokens,
profile: {
names: [
{
displayName: 'unknown',
}
],
emailAddresses: [
{
type: '',
value: 'unknown',
}
]
}
};
};
}
}
22 changes: 18 additions & 4 deletions packages/app/src/session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Session, OnBeforeSendHeadersListenerDetails, BeforeSendResponse } from 'electron';
import { Session, OnBeforeSendHeadersListenerDetails, BeforeSendResponse, OnHeadersReceivedListenerDetails, HeadersReceivedResponse } from 'electron';
import enhanceWebRequest from 'electron-better-web-request';

const orderListeners = (listeners: any) => {
Expand Down Expand Up @@ -78,7 +78,7 @@ const getUserAgentForApp = (url: string, currentUserAgent: string): string => {
return defaultUserAgent;
};

const getHeaderName = (headerName: string, headers?: Record<string, string>): string | undefined => {
const getHeaderName = (headerName: string, headers?: Record<string, string[]>): string | undefined => {
if (headers) {
const lowCaseHeader = headerName.toLowerCase();
for (const key in headers) {
Expand All @@ -90,12 +90,12 @@ const getHeaderName = (headerName: string, headers?: Record<string, string>): st
return undefined;
}

export const getHeader = (headerName: string, headers?: Record<string, any>): any => {
export const getHeader = (headerName: string, headers?: Record<string, string[]>): any => {
const realHeaderName = getHeaderName(headerName, headers);
return headers && realHeaderName ? headers[realHeaderName] : undefined;
}

export const setHeader = (headerName: string, headerValue: any, headers?: Record<string, any>) => {
export const setHeader = (headerName: string, headerValue: any, headers?: Record<string, string[]>): Record<string, string[]> | undefined => {
if (headers) {
const realHeaderName = getHeaderName(headerName, headers);
return {
Expand Down Expand Up @@ -132,4 +132,18 @@ export const enhanceSession = (session: Session) => {
});
}
);

session.webRequest.onHeadersReceived(
(details: OnHeadersReceivedListenerDetails, callback: (headersReceivedResponse: HeadersReceivedResponse) => void) => {
const responseHeaders = details.responseHeaders;

if (responseHeaders) {
delete responseHeaders['content-security-policy']; //vk: causes "This document requires 'TrustedHTML' assignment." error. Does not allow us to modify page CSS.
}

callback({
responseHeaders,
})
}
)
}

0 comments on commit bff44c6

Please sign in to comment.