aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-06-19 15:34:13 -0400
committerbobzel <zzzman@gmail.com>2025-06-19 15:34:13 -0400
commit21fb3a555cdd861452e2e54de3d0524e29f2bc08 (patch)
tree44b93ba0b4f9a85dafdb744ccb11dfe3386f4829 /src/server
parentabdfe5b109f42cd5da4aceef1bd667c8e1f6cbbd (diff)
parent765c7a3870a1d446622a28b157ab00a4dced2879 (diff)
Merge branch 'task_nodes_aarav'
Diffstat (limited to 'src/server')
-rw-r--r--src/server/ApiManagers/FireflyManager.ts11
-rw-r--r--src/server/ApiManagers/GeneralGoogleManager.ts135
-rw-r--r--src/server/RouteManager.ts8
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts11
-rw-r--r--src/server/apis/google/google_project_credentials.json8
-rw-r--r--src/server/authentication/DashUserModel.ts14
-rw-r--r--src/server/authentication/Passport.ts6
7 files changed, 174 insertions, 19 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 12913b1ef..110701418 100644
--- a/src/server/ApiManagers/GeneralGoogleManager.ts
+++ b/src/server/ApiManagers/GeneralGoogleManager.ts
@@ -3,6 +3,7 @@ import { Method } 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)],
@@ -61,5 +62,139 @@ export default class GeneralGoogleManager extends ApiManager {
res.send(undefined);
},
});
+
+ // Task Creation
+ register({
+ method: Method.POST,
+ subscription: new RouteSubscriber('googleTasks').add('create'),
+ secureHandler: async ({ req, res, user }) => {
+ try {
+ const auth = await GoogleApiServerUtils.retrieveOAuthClient(user.id);
+
+ if (!auth) {
+ return res.status(401).send('Google credentials missing or invalid.');
+ }
+
+ const tasks = google.tasks({ version: 'v1', auth });
+
+ const { title, notes, due, status, completed, deleted } = req.body;
+ const result = await tasks.tasks.insert({
+ tasklist: '@default',
+ requestBody: { title, notes, due, status, completed, deleted },
+ });
+
+ res.status(200).send(result.data);
+ } catch (err) {
+ console.error('Google Tasks error:', err);
+ res.status(500).send('Failed to create task.');
+ }
+ },
+ });
+
+ // Task Update
+ register({
+ method: Method.PATCH,
+ subscription: new RouteSubscriber('googleTasks').add('taskId'),
+ // any way to add static params? like /update (this is not very descriptive)
+ secureHandler: async ({ req, res, user }) => {
+ try {
+ const auth = await GoogleApiServerUtils.retrieveOAuthClient(user.id);
+
+ if (!auth) {
+ return res.status(401).send('Google credentials missing or invalid.');
+ }
+
+ const tasks = google.tasks({ version: 'v1', auth });
+
+ const { taskId } = req.params;
+ const { title, notes, due, status, completed, deleted } = req.body;
+
+ const result = await tasks.tasks.patch({
+ tasklist: '@default',
+ task: taskId,
+ requestBody: { title, notes, due, status, completed, deleted},
+ });
+
+ res.status(200).send(result.data);
+ } catch (err) {
+ console.error('Google Tasks update error:', err);
+ res.status(500).send('Failed to update task.');
+ }
+ },
+ });
+
+ // Task Deletion
+ register({
+ method: Method.DELETE,
+ subscription: new RouteSubscriber('googleTasks').add('taskId'),
+ secureHandler: async ({ req, res, user }) => {
+ try {
+ const auth = await GoogleApiServerUtils.retrieveOAuthClient(user.id);
+
+ if (!auth) {
+ return res.status(401).send('Google credentials missing or invalid.');
+ }
+
+ const tasks = google.tasks({ version: 'v1', auth });
+ const { taskId } = req.params;
+
+ await tasks.tasks.delete({
+ tasklist: '@default',
+ task: taskId,
+ });
+
+ res.status(200).send({ success: true });
+ } catch (err) {
+ console.error('Google Tasks delete error:', err);
+ res.status(500).send('Failed to delete task.');
+ }
+ },
+ });
+
+ // Google Account Linking
+
+ register({
+ method: Method.GET,
+ subscription: '/refreshGoogle',
+ secureHandler: async ({ user, req, res }) =>
+ new Promise<void>(resolve =>
+ GoogleApiServerUtils.processNewUser(user.id, req.query.code as string)
+ .then(() => res.status(200).send('Google account linked successfully!'))
+ .catch(err => {
+ console.error('Failed to process Google code:', err);
+ res.status(500).send('Error linking Google account');
+ })
+ .finally(resolve)
+ ),
+ });
+
+ // Task Retrieval
+ register({
+ method: Method.GET,
+ subscription: new RouteSubscriber('googleTasks').add('taskId'),
+ secureHandler: async ({ req, res, user }) => {
+ try {
+ const auth = await GoogleApiServerUtils.retrieveOAuthClient(user.id);
+
+ if (!auth) {
+ return res.status(401).send('Google credentials missing or invalid.');
+ }
+
+ const tasks = google.tasks({ version: 'v1', auth });
+ const { taskId } = req.params;
+
+ const result = await tasks.tasks.get({
+ tasklist: '@default',
+ task: taskId,
+ });
+
+ res.status(200).send(result.data);
+ } catch (err) {
+ console.error('Google Tasks retrieval error:', err);
+ res.status(500).send('Failed to retrieve task.');
+ }
+ },
+ });
}
+
}
diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts
index 2f6cf80b5..c5d70da3d 100644
--- a/src/server/RouteManager.ts
+++ b/src/server/RouteManager.ts
@@ -8,6 +8,8 @@ import { DashUserModel } from './authentication/DashUserModel';
export enum Method {
GET,
POST,
+ PATCH,
+ DELETE,
}
export interface CoreArguments {
@@ -207,6 +209,12 @@ export default class RouteManager {
case Method.POST:
this.server.post(route, supervised);
break;
+ case Method.PATCH:
+ this.server.patch(route, supervised);
+ break;
+ case Method.DELETE:
+ this.server.delete(route, supervised);
+ break;
default:
}
}
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 7373df473..ad0f0e580 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -13,7 +13,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}`
);
@@ -181,7 +181,7 @@ export namespace GoogleApiServerUtils {
* @returns the newly generated url to the authentication landing page
*/
export function generateAuthenticationUrl(): string {
- return worker.generateAuthUrl({ scope, access_type: 'offline' });
+ return worker.generateAuthUrl({ scope, access_type: 'offline', prompt: 'consent' });
}
/**
@@ -203,12 +203,12 @@ export namespace GoogleApiServerUtils {
*/
export async function processNewUser(userId: string, authenticationCode: string): Promise<EnrichedCredentials> {
const credentials = await new Promise<Credentials>((resolve, reject) => {
- worker.getToken(authenticationCode, (err, credentials) => {
- if (err || !credentials) {
+ worker.getToken(authenticationCode, (err, creds) => {
+ if (err || !creds) {
reject(err);
return;
}
- resolve(credentials);
+ resolve(creds);
});
});
const enriched = injectUserInfo(credentials);
@@ -304,6 +304,7 @@ export namespace GoogleApiServerUtils {
const { access_token, expires_in } = await new Promise<{ access_token: string; expires_in: number }>(resolve => {
request.post(url, headerParameters).then(response => resolve(JSON.parse(response)));
});
+
// 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);
diff --git a/src/server/apis/google/google_project_credentials.json b/src/server/apis/google/google_project_credentials.json
index 955c5a3c1..438e5157e 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": "740987818053-dtflji3hfkn5r9t8ad6jb8740pls8moh.apps.googleusercontent.com",
+ "project_id": "dash-web-461920",
"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",
- "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"]
+ "client_secret": "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",
+ "redirect_uris": ["http://localhost:1050/refreshGoogle"]
}
} \ No newline at end of file
diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts
index debeef60c..6fd8dd593 100644
--- a/src/server/authentication/DashUserModel.ts
+++ b/src/server/authentication/DashUserModel.ts
@@ -2,9 +2,10 @@ import * as bcrypt from 'bcrypt-nodejs';
import * as mongoose from 'mongoose';
import { Utils } from '../../Utils';
-type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => void) => void;
-export type DashUserModel = mongoose.Document & {
- email: String;
+type comparePasswordFunction = (candidatePassword: string, cb: (err: Error, isMatch: boolean) => void) => void;
+type mongooseDocument = { id: string }; // & mongoose.Document;
+export type DashUserModel = mongooseDocument & {
+ email: string;
password: string;
passwordResetToken?: string;
passwordResetExpires?: Date;
@@ -65,12 +66,13 @@ const userSchema = new mongoose.Schema(
/**
* Password hash middleware.
*/
-userSchema.pre('save', function save(next) {
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+userSchema.pre('save', function save(next: any) {
const user = this;
if (!user.isModified('password')) {
return next();
}
- bcrypt.genSalt(10, (err: any, salt: string) => {
+ bcrypt.genSalt(10, (err: Error, salt: string) => {
if (err) {
return next(err);
}
@@ -102,7 +104,7 @@ const comparePassword: comparePasswordFunction = function (this: DashUserModel,
userSchema.methods.comparePassword = comparePassword;
-const User: any = mongoose.model('User', userSchema);
+const User = mongoose.model('User', userSchema);
export function initializeGuest() {
new User({
email: 'guest',
diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts
index ca9e3058e..a62d38e3e 100644
--- a/src/server/authentication/Passport.ts
+++ b/src/server/authentication/Passport.ts
@@ -5,13 +5,13 @@ import User, { DashUserModel } from './DashUserModel';
const LocalStrategy = passportLocal.Strategy;
passport.serializeUser<any, any>((req, user, done) => {
- done(undefined, (user as any)?.id);
+ done(undefined, (user as DashUserModel)?.id);
});
passport.deserializeUser<any, any>((id, done) => {
User.findById(id)
.exec()
- .then((user: any) => done(undefined, user));
+ .then((user: DashUserModel) => done(undefined, user));
});
// AUTHENTICATE JUST WITH EMAIL AND PASSWORD
@@ -30,6 +30,6 @@ passport.use(
});
}
})
- .catch((error: any) => done(error));
+ .catch((error: Error) => done(error));
})
);