diff --git a/main.js b/main.js index 03bd2b4..6b1ae16 100644 --- a/main.js +++ b/main.js @@ -209,39 +209,23 @@ ipcMain.on('select-folder', (event) => { }); }); -ipcMain.on('start-sync', async (event, { destFolder, onedriveSource, items }) => { - console.log('Starting sync with config:', { destFolder, onedriveSource }); - console.log(`Processing ${items.length} items...`); - +ipcMain.handle('start-sync', async (event, { destFolder, onedriveSource }) => { + console.log('main.js start-sync:', { destFolder, onedriveSource }); try { - // Filter for video files (Live Photos) - const videoItems = items.filter(item => - item.name.toLowerCase().endsWith('.mov') || - item.name.toLowerCase().endsWith('.mp4') - ); - - console.log(`Found ${videoItems.length} video items`); - - // Process each video item - for (const item of videoItems) { - if (item['@microsoft.graph.downloadUrl']) { - const filename = `${item.id}${path.extname(item.name)}`; - const filepath = path.join(destFolder, filename); - - console.log(`Downloading: ${item.name} as ${filename}`); - await downloadVideo(item['@microsoft.graph.downloadUrl'], filepath); - } else { - console.warn(`No download URL for item: ${item.name}`); - } - } - - event.reply('sync-complete', { - totalItems: items.length, - videoItems: videoItems.length - }); - + const graphHelper = require('./renderer/graphHelper'); + const result = await graphHelper.listFolderContents(onedriveSource); + + // Send back the results using event.reply + // event.reply('sync-complete', { + // totalItems: result.value.length, + // videoItems: result.value.filter(item => + // item.name.toLowerCase().endsWith('.mov') || + // item.name.toLowerCase().endsWith('.mp4') + // ).length + // }); + } catch (error) { console.error('Sync error:', error); - event.reply('sync-error', error.message); + // event.reply('sync-error', error.message); } }); diff --git a/package-lock.json b/package-lock.json index c23274a..5922aed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@electron/remote": "^2.1.2", "@microsoft/microsoft-graph-client": "^3.0.2", "electron-store": "^10.0.0", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "uuid": "^11.0.4" }, "devDependencies": { @@ -51,9 +51,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -162,9 +162,9 @@ } }, "node_modules/@types/node": { - "version": "20.17.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", - "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", + "version": "20.17.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.16.tgz", + "integrity": "sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==", "dependencies": { "undici-types": "~6.19.2" } @@ -326,14 +326,6 @@ "node": ">=10" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, "node_modules/debounce-fn": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-6.0.0.tgz", @@ -451,17 +443,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dot-prop/node_modules/type-fest": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.31.0.tgz", - "integrity": "sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -471,9 +452,9 @@ } }, "node_modules/electron": { - "version": "33.2.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-33.2.1.tgz", - "integrity": "sha512-SG/nmSsK9Qg1p6wAW+ZfqU+AV8cmXMTIklUL18NnOKfZLlum4ZsDoVdmmmlL39ZmeCaq27dr7CgslRPahfoVJg==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-33.3.2.tgz", + "integrity": "sha512-2pWr0frM9UrZGX1d7eoFdMROw10h2vXIWJmXdjwlKnSWWUm18GCrEOUeDUr+IMgz5EjO7JM7FQDHDMApeMgHyg==", "hasInstallScript": true, "dependencies": { "@electron/get": "^2.0.0", @@ -488,9 +469,9 @@ } }, "node_modules/electron-store": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-10.0.0.tgz", - "integrity": "sha512-BU/QZh+5twHBprRdLu3YZX/rIarmZzhTNpJvAvqG1/yN0mNCrsMh0kl7bM4xaUKDNRiHz1r7wP/7Prjh7cleIw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-10.0.1.tgz", + "integrity": "sha512-Ok0bF13WWdTzZi9rCtPN8wUfwx+yDMmV6PAnCMqjNRKEXHmklW/rV+6DofV/Vf5qoAh+Bl9Bj7dQ+0W+IL2psg==", "dependencies": { "conf": "^13.0.0", "type-fest": "^4.20.0" @@ -502,17 +483,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-store/node_modules/type-fest": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.31.0.tgz", - "integrity": "sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -590,9 +560,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "funding": [ { "type": "github", @@ -612,39 +582,6 @@ "pend": "~1.2.0" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -954,39 +891,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "4.x || >=6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/normalize-url": { @@ -1152,6 +1073,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -1174,18 +1107,22 @@ "node": ">= 8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "optional": true, + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.33.0.tgz", + "integrity": "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1216,9 +1153,9 @@ } }, "node_modules/uuid": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.4.tgz", - "integrity": "sha512-IzL6VtTTYcAhA/oghbFJ1Dkmqev+FpQWnCBaKq/gUluLxliWvO8DPFWfIviRmYbtaavtSQe4WBL++rFjdcGWEg==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -1227,18 +1164,24 @@ "uuid": "dist/esm/bin/uuid" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/when-exit": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.3.tgz", - "integrity": "sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.4.tgz", + "integrity": "sha512-4rnvd3A1t16PWzrBUcSDZqcAmsUIy4minDXT/CZ8F2mVDgd65i4Aalimgz1aQkRGU0iH5eT5+6Rx2TK8o443Pg==" }, "node_modules/wrappy": { "version": "1.0.2", diff --git a/package.json b/package.json index 4487ba7..d6fe311 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,11 @@ "electron": "^33.2.1" }, "dependencies": { - "@electron/remote": "^2.1.2", - "electron-store": "^10.0.0", - "node-fetch": "^3.3.0", - "uuid": "^11.0.4", "@azure/msal-node": "^1.18.4", - "@microsoft/microsoft-graph-client": "^3.0.2" + "@electron/remote": "^2.1.2", + "@microsoft/microsoft-graph-client": "^3.0.2", + "electron-store": "^10.0.0", + "node-fetch": "^2.6.7", + "uuid": "^11.0.4" } } diff --git a/renderer/authConfig.js b/renderer/authConfig.js index ed70cd3..616dcc5 100644 --- a/renderer/authConfig.js +++ b/renderer/authConfig.js @@ -15,17 +15,16 @@ const AAD_ENDPOINT_HOST = "https://login.microsoftonline.com/"; // include the t const msalConfig = { auth: { clientId: "d581ab07-3a21-44d3-84c4-16b06bef6266", - authority: `${AAD_ENDPOINT_HOST}common`, + authority: "https://login.microsoftonline.com/consumers", + redirectUri: "msal" + "d581ab07-3a21-44d3-84c4-16b06bef6266" + "://auth" }, system: { loggerOptions: { - loggerCallback(loglevel, message, containsPii) { - console.log(message); - }, + loggerCallback: (loglevel, message) => console.log(message), piiLoggingEnabled: false, - logLevel: LogLevel.Verbose, - }, - }, + logLevel: LogLevel.Verbose + } + } }; /** @@ -38,12 +37,14 @@ const protectedResources = { graphMe: { endpoint: `${GRAPH_ENDPOINT_HOST}v1.0/me`, // scopes: ["User.Read"], - scopes: ["OneDrive.ReadWrite", "User.Read"] + scopes: ["Files.ReadWrite"] } }; +const graphScopes = ["Files.ReadWrite"]; // Modern scope for OneDrive access module.exports = { - msalConfig: msalConfig, + msalConfig, protectedResources: protectedResources, + graphScopes: graphScopes }; diff --git a/renderer/graphApi.js b/renderer/graphApi.js index f1436eb..e21a75a 100644 --- a/renderer/graphApi.js +++ b/renderer/graphApi.js @@ -1,17 +1,14 @@ const { BrowserWindow } = require('@electron/remote'); const { v4: uuidv4 } = require('uuid'); // Add this for GUID generation -const AuthProvider = require("./AuthProvider"); const { protectedResources, msalConfig } = require("./authConfig"); -let authProvider; class GraphApiClient { constructor() { this.baseUrl = 'https://graph.microsoft.com/v1.0'; - this.clientId = "073204aa-c1e0-4e66-a200-e5815a0aa93d"; - this.scopes = "OneDrive.ReadWrite offline_access openid profile"; - this.redirectUrl = "https://photos.onedrive.com/auth/login"; - + this.clientId = "d581ab07-3a21-44d3-84c4-16b06bef6266"; + this.scopes = "Files.ReadWrite offline_access"; + this.redirectUrl = "https://login.microsoftonline.com/common/oauth2/nativeclient"; } cleanPath(path) { @@ -23,52 +20,98 @@ class GraphApiClient { } async listFolderContents(folderPath) { + const accessToken = await this.getAccessToken(); + console.log("listFolderContents accessToken", accessToken); + // Remove AuthProvider usage completely + } + + async clearCaches() { + const session = require('@electron/remote').session; + const defaultSession = session.defaultSession; + try { - console.log('graphApiClient listFolderContents:', folderPath); - const tokenRequest = { - scopes: protectedResources.graphMe.scopes - }; - console.log('graphApiClient tokenRequest:', tokenRequest); - if (!authProvider) { - authProvider = new AuthProvider(msalConfig); - console.log('graphApiClient AuthProvider created', msalConfig); - } - - await authProvider.logout(); - const tokenResponse = await authProvider.getToken(tokenRequest); - const account = authProvider.account; - const accessToken = tokenResponse.accessToken; - console.log('graphApiClient Auth received: ', accessToken); - console.log('graphApiClient Auth received: ', account); + await Promise.all([ + defaultSession.clearStorageData({ + storages: [ + 'cookies', + 'localstorage', + 'cachestorage', + 'appcache', + 'filesystem', + 'indexdb', + 'shadercache', + 'websql', + 'serviceworkers', + ] + }), + defaultSession.clearCache(), + defaultSession.clearAuthCache() + ]); + console.log('All caches cleared successfully'); + } catch (error) { + console.error('Error clearing caches:', error); + throw error; + } + } - const cleanPath = this.cleanPath(folderPath); - console.log('graphApiClient Clean path:', cleanPath); - const url = `${this.baseUrl}/me/drive/root:/${cleanPath}:/children`; - - console.log('Querying OneDrive items from:', url); - - const response = await fetch(url, { - headers: { - 'Authorization': `Bearer ${accessToken}`, - 'Accept': 'application/json', - 'Cookie': auth.cookies, - 'Origin': 'https://onedrive.live.com', - 'Referer': 'https://onedrive.live.com/' + async getAccessToken() { + await this.clearCaches(); + + return new Promise((resolve, reject) => { + const authWindow = new BrowserWindow({ + width: 800, + height: 600, + show: true, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + webSecurity: false // Allow cross-origin requests } }); - if (!response.ok) { - const errorData = await response.json(); - console.error('Graph API error details:', errorData); - throw new Error(`Graph API error: ${response.status} ${response.statusText}`); + // Handle navigation events + authWindow.webContents.on('will-redirect', (event, url) => { + console.log('Redirect detected:', url); + this.handleAuthResponse(url, authWindow, resolve, reject); + }); + + authWindow.webContents.on('did-finish-load', () => { + console.log('Finished loading:', authWindow.webContents.getURL()); + }); + + const authUrl = `https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?` + + `client_id=${this.clientId}` + + `&response_type=token` + // Use token flow directly + `&scope=${encodeURIComponent(this.scopes)}` + + `&redirect_uri=${encodeURIComponent(this.redirectUrl)}` + + `&response_mode=fragment` + // Required for token flow + `&prompt=select_account`; + + console.log('Loading auth URL:', authUrl); + authWindow.loadURL(authUrl); + }); + } + + handleAuthResponse(url, authWindow, resolve, reject) { + if (url.startsWith(this.redirectUrl)) { + try { + const hash = new URL(url).hash.substring(1); + const params = new URLSearchParams(hash); + const accessToken = params.get('access_token'); + + if (accessToken) { + authWindow.close(); + resolve({ + accessToken: accessToken, + expiresIn: params.get('expires_in') + }); + } else { + reject(new Error('No access token found in response')); + } + } catch (error) { + console.error('Error processing auth response:', error); + reject(error); } - - const data = await response.json(); - return data.value; - - } catch (error) { - console.error('Graph API error:', error); - throw error; } } } diff --git a/renderer/graphHelper.js b/renderer/graphHelper.js new file mode 100644 index 0000000..d013e00 --- /dev/null +++ b/renderer/graphHelper.js @@ -0,0 +1,47 @@ +const { PublicClientApplication } = require('@azure/msal-node'); +const { msalConfig, graphScopes } = require('./authConfig'); +const fetch = (...args) => + import('node-fetch').then(({default: fetch}) => fetch(...args)); + +class GraphHelper { + constructor() { + this.pca = new PublicClientApplication(msalConfig); + } + + async getAccessToken() { + const accounts = await this.pca.getTokenCache().getAllAccounts(); + if (accounts.length > 0) { + try { + return await this.pca.acquireTokenSilent({ + account: accounts[0], + scopes: graphScopes + }); + } catch (error) { + return this.login(); + } + } + return this.login(); + } + + async login() { + return this.pca.acquireTokenInteractive({ + scopes: graphScopes, + openBrowser: async (url) => { + const { shell } = require('electron'); + await shell.openExternal(url); + } + }); + } + + async listFolderContents(folderPath) { + const token = await this.getAccessToken(); + const response = await fetch(`https://graph.microsoft.com/v1.0/me/drive/root:${folderPath}:/children`, { + headers: { + Authorization: `Bearer ${token.accessToken}` + } + }); + return response.json(); + } +} + +module.exports = new GraphHelper(); \ No newline at end of file diff --git a/renderer/renderer.js b/renderer/renderer.js index 86b41a7..7a95f94 100644 --- a/renderer/renderer.js +++ b/renderer/renderer.js @@ -74,25 +74,29 @@ document.getElementById('sync-button').addEventListener('click', async () => { alert('Please set both destination folder and OneDrive source path first'); return; } - + let originalText = "Sync Now"; try { // Show loading state const syncButton = document.getElementById('sync-button'); - const originalText = syncButton.textContent; + originalText = syncButton.textContent; + // const originalText = syncButton.textContent; syncButton.textContent = 'Syncing...'; syncButton.disabled = true; + // Get folder contents using GraphApiClient console.log('renderer: Getting folder contents:', onedriveSource); - const items = await graphApi.listFolderContents(onedriveSource); - console.log('renderer: Found items:', items.length); + // const items = await graphApi.listFolderContents(onedriveSource); + // console.log('renderer: Found items:', items.length); // Process the items // TODO: Handle the items as needed - showStatus(`Found ${items.length} items`); + // Send the items to the main process - ipcRenderer.send('start-sync', { destFolder, onedriveSource , items}); + // ipcRenderer.send('start-sync', { destFolder, onedriveSource }); + await ipcRenderer.invoke('start-sync', { destFolder, onedriveSource }); + } catch (error) { console.error('Sync error:', error);