aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorSkitty1238 <157652284+Skitty1238@users.noreply.github.com>2025-06-04 13:59:34 -0400
committerSkitty1238 <157652284+Skitty1238@users.noreply.github.com>2025-06-04 13:59:34 -0400
commit645df1d00f953524c6da22103d26c38ae4331cd6 (patch)
tree85fc3d4d3f0df579b5c53387d579e46b24e5c543 /src/server
parent5a998955235d141d2488c1c2deef50a3d6cf65c7 (diff)
partial google calendar task integration + fix with dark mode colors for task nodes so that text is still visible
Diffstat (limited to 'src/server')
-rw-r--r--src/server/ApiManagers/FireflyManager.ts11
-rw-r--r--src/server/ApiManagers/GeneralGoogleManager.ts73
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts39
-rw-r--r--src/server/apis/google/google_project_credentials.json6
-rw-r--r--src/server/authentication/DashUserModel.ts6
5 files changed, 89 insertions, 46 deletions
diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index 07ef271a1..6393a1f74 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -23,7 +23,16 @@ export default class FireflyManager extends ApiManager {
return undefined;
});
- generateImageFromStructure = (prompt: string = 'a realistic illustration of a cat coding', width: number = 2048, height: number = 2048, structureUrl: string, strength: number = 50, styles: string[], styleUrl: string | undefined, variations: number = 4) =>
+ generateImageFromStructure = (
+ prompt: string = 'a realistic illustration of a cat coding',
+ width: number = 2048,
+ height: number = 2048,
+ structureUrl: string,
+ strength: number = 50,
+ styles: string[],
+ styleUrl: string | undefined,
+ variations: number = 4
+ ) =>
this.getBearerToken().then(response =>
response?.json().then((data: { access_token: string }) =>
//prettier-ignore
diff --git a/src/server/ApiManagers/GeneralGoogleManager.ts b/src/server/ApiManagers/GeneralGoogleManager.ts
index aa06ca1b3..e8debfc12 100644
--- a/src/server/ApiManagers/GeneralGoogleManager.ts
+++ b/src/server/ApiManagers/GeneralGoogleManager.ts
@@ -1,11 +1,10 @@
import ApiManager, { Registration } from './ApiManager';
-import { Method } from '../RouteManager';
+import { Method, _success } from '../RouteManager';
import { GoogleApiServerUtils } from '../apis/google/GoogleApiServerUtils';
import RouteSubscriber from '../RouteSubscriber';
import { Database } from '../database';
import { google } from 'googleapis';
-
const EndpointHandlerMap = new Map<GoogleApiServerUtils.Action, GoogleApiServerUtils.ApiRouter>([
['create', (api, params) => api.create(params)],
['retrieve', (api, params) => api.get(params)],
@@ -18,9 +17,10 @@ export default class GeneralGoogleManager extends ApiManager {
method: Method.GET,
subscription: '/readGoogleAccessToken',
secureHandler: async ({ user, res }) => {
- const { credentials } = await GoogleApiServerUtils.retrieveCredentials(user.id);
+ const { credentials } = await GoogleApiServerUtils.retrieveCredentials(user);
if (!credentials?.access_token) {
- return res.send(GoogleApiServerUtils.generateAuthenticationUrl());
+ const url = GoogleApiServerUtils.generateAuthenticationUrl();
+ return res.send(url);
}
return res.send(credentials);
},
@@ -49,7 +49,7 @@ export default class GeneralGoogleManager extends ApiManager {
secureHandler: async ({ req, res, user }) => {
const sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service;
const action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action;
- const endpoint = await GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], user.id);
+ const endpoint = await GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], user);
const handler = EndpointHandlerMap.get(action);
if (endpoint && handler) {
try {
@@ -70,31 +70,48 @@ export default class GeneralGoogleManager extends ApiManager {
method: Method.POST,
subscription: new RouteSubscriber('googleTasks').add('create'),
secureHandler: async ({ req, res, user }) => {
- try {
- const { credentials } = await GoogleApiServerUtils.retrieveCredentials(user.id);
- if (!credentials?.access_token) {
- return res.status(401).send('Google access token not found.');
+ try {
+ const { credentials } = await GoogleApiServerUtils.retrieveCredentials(user.id);
+ const access_token = user.googleToken || credentials?.access_token; // if googleToken expires, we need to renew it.
+
+ if (!access_token) {
+ return res.status(401).send('Google access token not found.');
+ }
+
+ const auth = new google.auth.OAuth2();
+ auth.setCredentials({ access_token: access_token });
+
+ const tasks = google.tasks({ version: 'v1', auth });
+
+ const { title, notes, due } = req.body;
+ const result = await tasks.tasks.insert({
+ tasklist: '@default',
+ requestBody: { title, notes, due },
+ });
+
+ res.status(200).send(result.data);
+ } catch (err) {
+ console.error('Google Tasks error:', err);
+ res.status(500).send('Failed to create task.');
}
-
- const auth = new google.auth.OAuth2();
- auth.setCredentials({ access_token: credentials.access_token });
-
- const tasks = google.tasks({ version: 'v1', auth });
-
- const { title, notes, due } = req.body;
- const result = await tasks.tasks.insert({
- tasklist: '@default',
- requestBody: { title, notes, due },
- });
-
- res.status(200).send(result.data);
- } catch (err) {
- console.error('Google Tasks error:', err);
- res.status(500).send('Failed to create task.');
- }
},
- });
+ });
-
+ register({
+ method: Method.GET,
+ subscription: '/refreshGoogle',
+ secureHandler: async ({ user, req, res }) => {
+ const code = req.query.code as string;
+ _success(res, code);
+ user.googleToken = code;
+ user.save();
+
+ // const response2 = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode });
+ // runInAction(() => {
+ // this.success = true;
+ // this.credentials = response2 as { user_info: { name: string; picture: string }; access_token: string };
+ // });
+ },
+ });
}
}
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 7373df473..75f904331 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -6,6 +6,7 @@ import * as request from 'request-promise';
import { Opt } from '../../../fields/Doc';
import { Database } from '../../database';
import { GoogleCredentialsLoader } from './CredentialsLoader';
+import { DashUserModel } from '../../authentication/DashUserModel';
/**
* Scopes give Google users fine granularity of control
@@ -13,7 +14,7 @@ import { GoogleCredentialsLoader } from './CredentialsLoader';
* This is the somewhat overkill list of what Dash requests
* from the user.
*/
-const scope = ['documents.readonly', 'documents', 'presentations', 'presentations.readonly', 'drive', 'drive.file', 'photoslibrary', 'photoslibrary.appendonly', 'photoslibrary.sharing', 'userinfo.profile'].map(
+const scope = ['tasks', 'documents.readonly', 'documents', 'presentations', 'presentations.readonly', 'drive', 'drive.file', 'photoslibrary', 'photoslibrary.appendonly', 'photoslibrary.sharing', 'userinfo.profile'].map(
relative => `https://www.googleapis.com/auth/${relative}`
);
@@ -118,8 +119,9 @@ export namespace GoogleApiServerUtils {
* @param userId the id of the Dash user making the request to the API
* @returns the relevant 'googleapis' wrapper, if any
*/
- export async function GetEndpoint(sector: string, userId: string): Promise<Endpoint | void> {
- const auth = await retrieveOAuthClient(userId);
+ export async function GetEndpoint(sector: string, user: DashUserModel): Promise<Endpoint | void> {
+ if (!user.googleToken) await retrieveOAuthClient(user);
+ const auth = user.googleToken; // await retrieveOAuthClient(user);
if (!auth) {
return;
}
@@ -145,14 +147,14 @@ export namespace GoogleApiServerUtils {
* npm-installed API wrappers that use authenticated client instances rather than access codes for
* security.
*/
- export async function retrieveOAuthClient(userId: string): Promise<OAuth2Client | void> {
- const { credentials, refreshed } = await retrieveCredentials(userId);
+ export async function retrieveOAuthClient(user: DashUserModel): Promise<OAuth2Client | void> {
+ const { credentials, refreshed } = await retrieveCredentials(user);
if (!credentials) {
return;
}
- let client = authenticationClients.get(userId);
+ let client = authenticationClients.get(user.id);
if (!client) {
- authenticationClients.set(userId, (client = generateClient(credentials)));
+ authenticationClients.set(user.id, (client = generateClient(credentials)));
} else if (refreshed) {
client.setCredentials(credentials);
}
@@ -181,7 +183,16 @@ export namespace GoogleApiServerUtils {
* @returns the newly generated url to the authentication landing page
*/
export function generateAuthenticationUrl(): string {
- return worker.generateAuthUrl({ scope, access_type: 'offline' });
+ const oauth2Client = new google.auth.OAuth2(
+ '838617994486-a28072lirm8uk8cm78t7ic4krp0rgkgv.apps.googleusercontent.com',
+ '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',
+ 'http://localhost:1050/refreshGoogle' // Ensure this matches the redirect URI in Google Cloud Console
+ );
+
+ return oauth2Client.generateAuthUrl({
+ access_type: 'offline',
+ scope: ['https://www.googleapis.com/auth/tasks'],
+ });
}
/**
@@ -267,15 +278,15 @@ export namespace GoogleApiServerUtils {
* @returns the credentials, or undefined if the user has no stored associated credentials,
* and a flag indicating whether or not they were refreshed during retrieval
*/
- export async function retrieveCredentials(userId: string): Promise<{ credentials: Opt<EnrichedCredentials>; refreshed: boolean }> {
- let credentials = await Database.Auxiliary.GoogleAccessToken.Fetch(userId);
+ export async function retrieveCredentials(user: DashUserModel): Promise<{ credentials: Opt<EnrichedCredentials>; refreshed: boolean }> {
+ let credentials = await Database.Auxiliary.GoogleAccessToken.Fetch(user.id);
let refreshed = false;
if (!credentials) {
return { credentials: undefined, refreshed };
}
// check for token expiry
if (credentials.expiry_date! <= new Date().getTime()) {
- credentials = { ...credentials, ...(await refreshAccessToken(credentials, userId)) };
+ credentials = { ...credentials, ...(await refreshAccessToken(credentials, user)) };
refreshed = true;
}
return { credentials, refreshed };
@@ -291,11 +302,11 @@ export namespace GoogleApiServerUtils {
* his/her credentials be refreshed
* @returns the updated credentials
*/
- async function refreshAccessToken(credentials: Credentials, userId: string): Promise<Credentials> {
+ async function refreshAccessToken(credentials: Credentials, user: DashUserModel): Promise<Credentials> {
const headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } };
const { client_id, client_secret } = GoogleCredentialsLoader.ProjectCredentials;
const params = new URLSearchParams({
- refresh_token: credentials.refresh_token!,
+ refresh_token: credentials.refresh_token!, // AARAV use user.googleToken
client_id,
client_secret,
grant_type: 'refresh_token',
@@ -306,7 +317,7 @@ export namespace GoogleApiServerUtils {
});
// expires_in is in seconds, but we're building the new expiry date in milliseconds
const expiry_date = new Date().getTime() + expires_in * 1000;
- await Database.Auxiliary.GoogleAccessToken.Update(userId, access_token, expiry_date);
+ await Database.Auxiliary.GoogleAccessToken.Update(user.id, access_token, expiry_date);
// update the relevant properties
credentials.access_token = access_token;
credentials.expiry_date = expiry_date;
diff --git a/src/server/apis/google/google_project_credentials.json b/src/server/apis/google/google_project_credentials.json
index 955c5a3c1..738e13647 100644
--- a/src/server/apis/google/google_project_credentials.json
+++ b/src/server/apis/google/google_project_credentials.json
@@ -1,11 +1,11 @@
{
"installed": {
- "client_id": "343179513178-ud6tvmh275r2fq93u9eesrnc66t6akh9.apps.googleusercontent.com",
- "project_id": "quickstart-1565056383187",
+ "client_id": "838617994486-a28072lirm8uk8cm78t7ic4krp0rgkgv.apps.googleusercontent.com",
+ "project_id": "gtasks-test-dash",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
- "client_secret": "w8KIFSc0MQpmUYHed4qEzn8b",
+ "client_secret": "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",
"redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"]
}
} \ No newline at end of file
diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts
index debeef60c..4397e2bd4 100644
--- a/src/server/authentication/DashUserModel.ts
+++ b/src/server/authentication/DashUserModel.ts
@@ -9,9 +9,14 @@ export type DashUserModel = mongoose.Document & {
passwordResetToken?: string;
passwordResetExpires?: Date;
+
+ // AARAV ADD
+ googleToken?: string;
+
dropboxRefresh?: string;
dropboxToken?: string;
+
userDocumentId: string;
sharingDocumentId: string;
linkDatabaseId: string;
@@ -40,6 +45,7 @@ const userSchema = new mongoose.Schema(
passwordResetToken: String,
passwordResetExpires: Date,
+ googleToken: String,
dropboxRefresh: String,
dropboxToken: String,
userDocumentId: String, // id that identifies a document which hosts all of a user's account data