From bacbbe35d764ec3187789a57641ef90e465f4c19 Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 30 Sep 2021 14:25:56 +0100 Subject: [PATCH] Refactored MSL This refactored MSL should help with the authentication token issues that happen way too frequently. --- app/assets/css/launcher.css | 13 +- app/assets/js/authmanager.js | 126 ++++---- app/assets/js/configmanager.js | 4 +- app/assets/js/microsoft.js | 359 +++++++++------------- app/assets/js/scripts/login.js | 23 +- app/assets/js/scripts/settings.js | 7 +- app/login.ejs | 23 +- app/overlay.ejs | 6 +- index.js | 37 ++- package-lock.json | 485 ++++++++++++++++++++++++------ package.json | 1 + 11 files changed, 655 insertions(+), 429 deletions(-) diff --git a/app/assets/css/launcher.css b/app/assets/css/launcher.css index d95e1c8a..25728fc8 100644 --- a/app/assets/css/launcher.css +++ b/app/assets/css/launcher.css @@ -869,28 +869,31 @@ body, button { } #loginMSButton { - background: none; + background-color: #006EFA; border: none; margin-top: 5px; margin-bottom: 10px; font-size: 20px; + display: flex; + padding: 16px; + gap: 15px; + font-weight: bold; + align-items: center; + cursor: pointer; } #loginMSButton:disabled { color: rgba(255, 255, 255, 0.75); pointer-events: none; } - #loginMSButton:hover, #loginMSButton:focus { text-shadow: 0px 0px 20px #fff; outline: none; } - #loginMSButton:active { color: #c7c7c7; text-shadow: 0px 0px 20px #c7c7c7; -} - +} /* #login_filter { height: calc(100% - 22px); diff --git a/app/assets/js/authmanager.js b/app/assets/js/authmanager.js index 88101961..367caed7 100644 --- a/app/assets/js/authmanager.js +++ b/app/assets/js/authmanager.js @@ -19,14 +19,14 @@ const loggerSuccess = LoggerUtil('%c[AuthManager]', 'color: #209b07; font-weight async function validateSelectedMojang() { const current = ConfigManager.getSelectedAccount() const isValid = await Mojang.validate(current.accessToken, ConfigManager.getClientToken()) - if(!isValid){ + if (!isValid) { try { const session = await Mojang.refresh(current.accessToken, ConfigManager.getClientToken()) ConfigManager.updateAuthAccount(current.uuid, session.accessToken) ConfigManager.save() - } catch(err) { + } catch (err) { logger.debug('Error while validating selected profile:', err) - if(err && err.error === 'ForbiddenOperationException'){ + if (err && err.error === 'ForbiddenOperationException') { // What do we do? } logger.log('Account access token is invalid.') @@ -41,34 +41,30 @@ async function validateSelectedMojang() { } async function validateSelectedMicrosoft() { - try { - const current = ConfigManager.getSelectedAccount() - const now = new Date().getTime() - const MCExpiresAt = Date.parse(current.expiresAt) - const MCExpired = now > MCExpiresAt + const current = ConfigManager.getSelectedAccount() + const now = new Date().getTime() + const MCExpiresAt = Date.parse(current.expiresAt) + const MCExpired = now > MCExpiresAt - if(MCExpired) { - const MSExpiresAt = Date.parse(current.microsoft.expires_at) - const MSExpired = now > MSExpiresAt - - if (MSExpired) { - const newAccessToken = await Microsoft.refreshAccessToken(current.microsoft.refresh_token) - const newMCAccessToken = await Microsoft.authMinecraft(newAccessToken.access_token) - ConfigManager.updateAuthAccount(current.uuid, newMCAccessToken.access_token, newAccessToken.expires_at) - ConfigManager.save() - return true - } - const newMCAccessToken = await Microsoft.authMinecraft(current.microsoft.access_token) - ConfigManager.updateAuthAccount(current.uuid, newMCAccessToken.access_token, current.microsoft.access_token, current.microsoft.expires_at, newMCAccessToken.expires_at) - ConfigManager.save() - - return true - } else { - return true - } - } catch (error) { - return Promise.reject(error) + if (!MCExpired) { + return true } + + const MSExpiresAt = Date.parse(current.microsoft.expires_at) + const MSExpired = now > MSExpiresAt + + if (MSExpired) { + const newAccessToken = await Microsoft.refreshAccessToken(current.microsoft.refresh_token) + const newMCAccessToken = await Microsoft.authMinecraft(newAccessToken.access_token) + ConfigManager.updateAuthAccount(current.uuid, newMCAccessToken.access_token, newAccessToken.expires_at) + ConfigManager.save() + return true + } + const newMCAccessToken = await Microsoft.authMinecraft(current.microsoft.access_token) + ConfigManager.updateAuthAccount(current.uuid, newMCAccessToken.access_token, current.microsoft.access_token, current.microsoft.expires_at, newMCAccessToken.expires_at) + ConfigManager.save() + + return true } // Exports @@ -109,21 +105,18 @@ exports.addAccount = async function(username, password){ * @param {string} uuid The UUID of the account to be removed. * @returns {Promise.} Promise which resolves to void when the action is complete. */ + exports.removeAccount = async function(uuid){ - try { - const authAcc = ConfigManager.getAuthAccount(uuid) - if(authAcc.type === 'microsoft'){ - ConfigManager.removeAuthAccount(uuid) - ConfigManager.save() - return Promise.resolve() - } - await Mojang.invalidate(authAcc.accessToken, ConfigManager.getClientToken()) + const authAcc = ConfigManager.getAuthAccount(uuid) + if (authAcc.type === 'microsoft') { ConfigManager.removeAuthAccount(uuid) ConfigManager.save() - return Promise.resolve() - } catch (err){ - return Promise.reject(err) + return } + await Mojang.invalidate(authAcc.accessToken, ConfigManager.getClientToken()) + ConfigManager.removeAuthAccount(uuid) + ConfigManager.save() + return } /** @@ -139,36 +132,31 @@ exports.removeAccount = async function(uuid){ exports.validateSelected = async function(){ const current = ConfigManager.getSelectedAccount() const isValid = await Mojang.validate(current.accessToken, ConfigManager.getClientToken()) - if(!isValid){ - try{ - if (ConfigManager.getSelectedAccount() === 'microsoft') { - const validate = await validateSelectedMicrosoft() - return validate - } else { - const validate = await validateSelectedMojang() - return validate - } - } catch (error) { - return Promise.reject(error) - } - } else return true + if (isValid) { + return true + } + + if (ConfigManager.getSelectedAccount() === 'microsoft') { + const validate = await validateSelectedMicrosoft() + return validate + } else { + const validate = await validateSelectedMojang() + return validate + } } -exports.addMSAccount = async authCode => { - try { - const accessToken = await Microsoft.getAccessToken(authCode) - const MCAccessToken = await Microsoft.authMinecraft(accessToken.access_token) - const minecraftBuyed = await Microsoft.checkMCStore(MCAccessToken.access_token) - if(!minecraftBuyed) - return Promise.reject({ - message: 'You didn\'t buy Minecraft! Please use another Microsoft account or buy Minecraft.' - }) - const MCProfile = await Microsoft.getMCProfile(MCAccessToken.access_token) - const ret = ConfigManager.addMsAuthAccount(MCProfile.id, MCAccessToken.access_token, MCProfile.name, MCAccessToken.expires_at, accessToken.access_token, accessToken.refresh_token) - ConfigManager.save() - return ret - } catch(error) { - return Promise.reject(error) - } +exports.addMSAccount = async authCode => { + const accessToken = await Microsoft.getAccessToken(authCode) + const MCAccessToken = await Microsoft.authMinecraft(accessToken.access_token) + const minecraftBuyed = await Microsoft.checkMCStore(MCAccessToken.access_token) + if (!minecraftBuyed) + throw { + message: 'You didn\'t buy Minecraft! Please use another Microsoft account or buy Minecraft.' + } + const MCProfile = await Microsoft.getMCProfile(MCAccessToken.access_token) + const result = ConfigManager.addMsAuthAccount(MCProfile.id, MCAccessToken.access_token, MCProfile.name, MCAccessToken.expires_at, accessToken.access_token, accessToken.refresh_token) + ConfigManager.save() + + return result } \ No newline at end of file diff --git a/app/assets/js/configmanager.js b/app/assets/js/configmanager.js index a0838476..9a6abd31 100644 --- a/app/assets/js/configmanager.js +++ b/app/assets/js/configmanager.js @@ -382,7 +382,7 @@ exports.updateAuthAccount = function(uuid, accessToken){ * * @returns {Object} The authenticated account object created by this action. */ -exports.updateAuthAccount = function(uuid, accessToken, msAccessToken, msRefreshToken, msExpires, mcExpires){ + exports.updateAuthAccount = function (uuid, accessToken, msAccessToken, msRefreshToken, msExpires, mcExpires) { config.authenticationDatabase[uuid].accessToken = accessToken config.authenticationDatabase[uuid].expiresAt = mcExpires config.authenticationDatabase[uuid].microsoft.access_token = msAccessToken @@ -426,7 +426,7 @@ exports.addAuthAccount = function(uuid, accessToken, username, displayName){ * * @returns {Object} The authenticated account object created by this action. */ -exports.addMsAuthAccount = function(uuid, accessToken, name, mcExpires, msAccessToken, msRefreshToken, msExpires){ +exports.addMsAuthAccount = function (uuid, accessToken, name, mcExpires, msAccessToken, msRefreshToken, msExpires) { config.selectedAccount = uuid config.authenticationDatabase[uuid] = { accessToken, diff --git a/app/assets/js/microsoft.js b/app/assets/js/microsoft.js index 67151dbd..0384ee0e 100644 --- a/app/assets/js/microsoft.js +++ b/app/assets/js/microsoft.js @@ -1,225 +1,162 @@ -// Requirements -const request = require('request') +const got = require('got').extend({ + responseType: 'json', + resolveBodyOnly: true +}) -// Constants -const clientId = '71a6e661-ee73-4166-a21a-26ce6e15b3de' +// TODO: Add client ID (https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade) +const CLIENT_ID = '71a6e661-ee73-4166-a21a-26ce6e15b3de' -const tokenUri = 'https://login.microsoftonline.com/consumers/oauth2/v2.0/token' -const authXBLUri = 'https://user.auth.xboxlive.com/user/authenticate' -const authXSTSUri = 'https://xsts.auth.xboxlive.com/xsts/authorize' -const authMCUri = 'https://api.minecraftservices.com/authentication/login_with_xbox' -const profileURI = 'https://api.minecraftservices.com/minecraft/profile' +const TOKEN_URI = 'https://login.microsoftonline.com/consumers/oauth2/v2.0/token' +const AUTH_XBL_URI = 'https://user.auth.xboxlive.com/user/authenticate' +const AUTH_XSTS_URI = 'https://xsts.auth.xboxlive.com/xsts/authorize' +const AUTH_MC_URI = 'https://api.minecraftservices.com/authentication/login_with_xbox' +const PROFILE_URI = 'https://api.minecraftservices.com/minecraft/profile' -// Functions -function requestPromise(uri, options) { - return new Promise((resolve, reject) => { - request(uri, options, (error, response, body) => { - if (error) { - reject(error) - } else if (response.statusCode !== 200) { - reject([response.statusCode, response.statusMessage, response]) - } else { - resolve(response) - } - }) - }) -} - -function getXBLToken(accessToken) { - return new Promise((resolve, reject) => { - const data = new Object() - - const options = { - method: 'post', - json: { - Properties: { - AuthMethod: 'RPS', - SiteName: 'user.auth.xboxlive.com', - RpsTicket: `d=${accessToken}` - }, - RelyingParty: 'http://auth.xboxlive.com', - TokenType: 'JWT' - } +async function getXBLToken(accessToken) { + const { + Token: token, + DisplayClaims: displayClaims + } = await got.post(AUTH_XBL_URI, { + json: { + Properties: { + AuthMethod: 'RPS', + SiteName: 'user.auth.xboxlive.com', + RpsTicket: `d=${accessToken}` + }, + RelyingParty: 'http://auth.xboxlive.com', + TokenType: 'JWT' } - requestPromise(authXBLUri, options).then(response => { - const body = response.body - - data.token = body.Token - data.uhs = body.DisplayClaims.xui[0].uhs - - resolve(data) - }).catch(error => { - reject(error) - }) }) -} -function getXSTSToken(XBLToken) { - return new Promise((resolve, reject) => { - const options = { - method: 'post', - json: { - Properties: { - SandboxId: 'RETAIL', - UserTokens: [XBLToken] - }, - RelyingParty: 'rp://api.minecraftservices.com/', - TokenType: 'JWT' - } - } - requestPromise(authXSTSUri, options).then(response => { - if (response.body.XErr) { - switch (response.body.XErr) { - case 2148916233: - reject({ - message: 'Your Microsoft account is not connected to an Xbox account. Please create one.
' - }) - return - - case 2148916238: - reject({ - message: 'Since you are not yet 18 years old, an adult must add you to a family in order for you to use Helios Launcher!' - }) - return - - } - reject(response.body) - } - resolve(response.body.Token) - }).catch(error => { - reject(error) - }) - }) -} - -function getMCAccessToken(UHS, XSTSToken) { - return new Promise((resolve, reject) => { - const data = new Object() - const expiresAt = new Date() - - const options = { - method: 'post', - json: { - identityToken: `XBL3.0 x=${UHS};${XSTSToken}` - } - } - requestPromise(authMCUri, options).then(response => { - const body = response.body - - expiresAt.setSeconds(expiresAt.getSeconds() + body.expires_in) - data.access_token = body.access_token - data.expires_at = expiresAt - - resolve(data) - }).catch(error => { - reject(error) - }) - }) -} - -// Exports -exports.getAccessToken = authCode => { - return new Promise((resolve, reject) => { - const expiresAt = new Date() - const data = new Object() - - const options = { - method: 'post', - formData: { - client_id: clientId, - code: authCode, - scope: 'XboxLive.signin', - redirect_uri: 'https://login.microsoftonline.com/common/oauth2/nativeclient', - grant_type: 'authorization_code' - } - } - requestPromise(tokenUri, options).then(response => { - const body = JSON.parse(response.body) - expiresAt.setSeconds(expiresAt.getSeconds() + body.expires_in) - data.expires_at = expiresAt - data.access_token = body.access_token - data.refresh_token = body.refresh_token - - resolve(data) - }).catch(error => { - reject(error) - }) - }) -} - -exports.refreshAccessToken = refreshToken => { - return new Promise((resolve, reject) => { - const expiresAt = new Date() - const data = new Object() - - const options = { - method: 'post', - formData: { - client_id: clientId, - refresh_token: refreshToken, - scope: 'XboxLive.signin', - redirect_uri: 'https://login.microsoftonline.com/common/oauth2/nativeclient', - grant_type: 'refresh_token' - } - } - requestPromise(tokenUri, options).then(response => { - const body = JSON.parse(response.body) - expiresAt.setSeconds(expiresAt.getSeconds() + body.expires_in) - data.expires_at = expiresAt - data.access_token = body.access_token - - resolve(data) - }).catch(error => { - reject(error) - }) - }) -} - -exports.authMinecraft = async accessToken => { - try { - const XBLToken = await getXBLToken(accessToken) - const XSTSToken = await getXSTSToken(XBLToken.token) - const MCToken = await getMCAccessToken(XBLToken.uhs, XSTSToken) - - return MCToken - } catch (error) { - Promise.reject(error) + return { + token, + uhs: displayClaims.xui[0].uhs } } -exports.checkMCStore = async function(access_token){ - return new Promise((resolve, reject) => { - request.get({ - url: 'https://api.minecraftservices.com/entitlements/mcstore', - json: true, - headers: { - Authorization: 'Bearer ' + access_token - } - }, (err, res, body) => { - if (err) { - resolve(false) - return - } - if(body.items && body.items.length > 0) resolve(true) - else resolve(false) - }) +async function getXSTSToken(XBLToken) { + const data = await got.post(AUTH_XSTS_URI, { + json: { + Properties: { + SandboxId: 'RETAIL', + UserTokens: [XBLToken] + }, + RelyingParty: 'rp://api.minecraftservices.com/', + TokenType: 'JWT' + } }) + + if (data.XErr) { + switch (data.XErr) { + case 2148916233: + throw { + message: 'Your Microsoft account is not connected to an Xbox account. Please create one.
' + } + case 2148916238: + throw { + message: 'Since you are not yet 18 years old, an adult must add you to a family in order for you to use Helios Launcher!' + } + } + throw data + } + + return data.Token } -exports.getMCProfile = MCAccessToken => { - return new Promise((resolve, reject) => { - const options = { - method: 'get', - headers: { - Authorization: `Bearer ${MCAccessToken}` - } +async function getMCAccessToken(UHS, XSTSToken) { + const data = await got.post(AUTH_MC_URI, { + json: { + identityToken: `XBL3.0 x=${UHS};${XSTSToken}` } - requestPromise(profileURI, options).then(response => { - const body = JSON.parse(response.body) - - resolve(body) - }).catch(error => { - reject(error) - }) }) -} + + const expiresAt = new Date() + expiresAt.setSeconds(expiresAt.getSeconds() + data.expires_in) + + return { + expired_at: expiresAt, + access_token: data.access_token + } +} + +exports.getAccessToken = async authCode => { + const { + expires_in, + access_token, + refresh_token + } = await got.post(TOKEN_URI, { + form: { + client_id: CLIENT_ID, + code: authCode, + scope: 'XboxLive.signin', + redirect_uri: 'https://login.microsoftonline.com/common/oauth2/nativeclient', + grant_type: 'authorization_code' + } + }) + + const expiresAt = new Date() + expiresAt.setSeconds(expiresAt.getSeconds() + expires_in) + + return { + expires_at: expiresAt, + access_token, + refresh_token + } +} + +exports.refreshAccessToken = async refreshToken => { + const { + expires_in, + access_token + } = await got.post(TOKEN_URI, { + form: { + client_id: CLIENT_ID, + refresh_token: refreshToken, + scope: 'XboxLive.signin', + redirect_uri: 'https://login.microsoftonline.com/common/oauth2/nativeclient', + grant_type: 'refresh_token' + }, + responseType: 'json' + }) + + const expiresAt = new Date() + expiresAt.setSeconds(expiresAt.getSeconds() + expires_in) + + return { + expires_at: expiresAt, + access_token + } +} + +exports.authMinecraft = async accessToken => { + const XBLToken = await getXBLToken(accessToken) + const XSTSToken = await getXSTSToken(XBLToken.token) + const MCToken = await getMCAccessToken(XBLToken.uhs, XSTSToken) + + return MCToken +} + +exports.checkMCStore = async access_token => { + try { + const {items} = await got('https://api.minecraftservices.com/entitlements/mcstore', { + headers: { + Authorization: 'Bearer ' + access_token + }, + responseType: 'json' + }) + + return items && items.length > 0 + } catch { + return false + } +} + +exports.getMCProfile = async MCAccessToken => { + const data = await got(PROFILE_URI, { + headers: { + Authorization: `Bearer ${MCAccessToken}` + } + }) + + return data +} \ No newline at end of file diff --git a/app/assets/js/scripts/login.js b/app/assets/js/scripts/login.js index 0a534ebd..fd4bda3b 100644 --- a/app/assets/js/scripts/login.js +++ b/app/assets/js/scripts/login.js @@ -330,19 +330,18 @@ loginButton.addEventListener('click', () => { }) -loginMSButton.addEventListener('click', (event) => { +loginMSButton.addEventListener('click', () => { // Show loading stuff. toggleOverlay(true, false, 'msOverlay') loginMSButton.disabled = true ipcRenderer.send('openMSALoginWindow', 'open') }) -ipcRenderer.on('MSALoginWindowReply', (event, ...args) => { - if (args[0] === 'error') { - +ipcRenderer.on('MSALoginWindowReply', (_, ...arguments_) => { + if (arguments_[0] === 'error') { loginMSButton.disabled = false loginLoading(false) - switch (args[1]){ + switch (arguments_[1]) { case 'AlreadyOpenException': { setOverlayContent('ERROR', 'There is already a login window open!', 'OK') setOverlayHandler(() => { @@ -362,17 +361,17 @@ ipcRenderer.on('MSALoginWindowReply', (event, ...args) => { return } } - + } toggleOverlay(false, false, 'msOverlay') - const queryMap = args[0] + const queryMap = arguments_[0] if (queryMap.has('error')) { let error = queryMap.get('error') let errorDesc = queryMap.get('error_description') - if(error === 'access_denied'){ + if (error === 'access_denied') { error = 'ERRPR' - errorDesc = 'To use the Vicarious Network Launcher, you must agree to the required permissions! Otherwise you can\'t use this launcher with Microsoft accounts.

Despite agreeing to the permissions you don\'t give us the possibility to do anything with your account, because all data will always be sent back to you (the launcher) IMMEDIATELY and WITHOUT WAY.' - } + errorDesc = 'To use the Helios Launcher, you must agree to the required permissions! Otherwise you can\'t use this launcher with Microsoft accounts.

Despite agreeing to the permissions you don\'t give us the possibility to do anything with your account, because all data will always be sent back to you (the launcher) IMMEDIATELY and WITHOUT WAY.' + } setOverlayContent(error, errorDesc, 'OK') setOverlayHandler(() => { loginMSButton.disabled = false @@ -407,8 +406,9 @@ ipcRenderer.on('MSALoginWindowReply', (event, ...args) => { loginLoading(false) loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.success'), Lang.queryJS('login.login')) formDisabled(false) + toggleOverlay(false) + toggleOverlay(false, false, 'msOverlay') }) - toggleOverlay(false) }, 1000) }).catch(error => { loginMSButton.disabled = false @@ -421,5 +421,4 @@ ipcRenderer.on('MSALoginWindowReply', (event, ...args) => { toggleOverlay(true) loggerLogin.error(error) }) - }) diff --git a/app/assets/js/scripts/settings.js b/app/assets/js/scripts/settings.js index 916ab220..185c792e 100644 --- a/app/assets/js/scripts/settings.js +++ b/app/assets/js/scripts/settings.js @@ -455,7 +455,7 @@ function bindAuthAccountLogOut() { }) } -let data = null +let data = null /** * Process a log out. @@ -463,7 +463,7 @@ let data = null * @param {Element} val The log out button element. * @param {boolean} isLastAccount If this logout is on the last added account. */ -function processLogOut(val, isLastAccount, skip = false) { + function processLogOut(val, isLastAccount, skip = false) { data = { val, isLastAccount @@ -479,7 +479,9 @@ function processLogOut(val, isLastAccount, skip = false) { ipcRenderer.send('openMSALogoutWindow', 'open') } } + const prevSelAcc = ConfigManager.getSelectedAccount() + AuthManager.removeAccount(uuid).then(() => { if (!isLastAccount && uuid === prevSelAcc.uuid) { const selAcc = ConfigManager.getSelectedAccount() @@ -488,6 +490,7 @@ function processLogOut(val, isLastAccount, skip = false) { validateSelectedAccount() } }) + $(parent).fadeOut(150, () => { parent.remove() }) diff --git a/app/login.ejs b/app/login.ejs index cf31edc1..a9031525 100644 --- a/app/login.ejs +++ b/app/login.ejs @@ -61,17 +61,18 @@ or
- +
Need an Account? diff --git a/app/overlay.ejs b/app/overlay.ejs index 521325d2..d1b349db 100644 --- a/app/overlay.ejs +++ b/app/overlay.ejs @@ -39,8 +39,10 @@
\ No newline at end of file diff --git a/index.js b/index.js index 4a333bb5..034b7211 100644 --- a/index.js +++ b/index.js @@ -10,8 +10,9 @@ const path = require('path') const semver = require('semver') const { pathToFileURL } = require('url') + const redirectUriPrefix = 'https://login.microsoftonline.com/common/oauth2/nativeclient?' -const clientID = '71a6e661-ee73-4166-a21a-26ce6e15b3de' +const CLIENT_ID = '71a6e661-ee73-4166-a21a-26ce6e15b3de' // TODO: Add client ID (https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade) if(isDev) { console.log('Is in dev mode!') @@ -98,11 +99,11 @@ ipcMain.on('cachedDistributionNotification', (event, res) => { // https://electronjs.org/docs/tutorial/offscreen-rendering app.disableHardwareAcceleration() -let MSALoginWindow = null +let MSALoginWindow // Open the Microsoft Account Login window -ipcMain.on('openMSALoginWindow', (ipcEvent, args) => { - if (MSALoginWindow != null) { +ipcMain.on('openMSALoginWindow', (ipcEvent) => { + if (MSALoginWindow) { ipcEvent.reply('MSALoginWindowReply', 'error', 'AlreadyOpenException') return } @@ -116,23 +117,21 @@ ipcMain.on('openMSALoginWindow', (ipcEvent, args) => { }) MSALoginWindow.on('closed', () => { - - MSALoginWindow = null + MSALoginWindow = undefined }) - MSALoginWindow.on('close', event => { + MSALoginWindow.on('close', () => { ipcEvent.reply('MSALoginWindowReply', 'error', 'AuthNotFinished') - }) - MSALoginWindow.webContents.on('did-navigate', (event, uri, responseCode, statusText) => { + MSALoginWindow.webContents.on('did-navigate', (_, uri) => { if (uri.startsWith(redirectUriPrefix)) { - let querys = uri.substring(redirectUriPrefix.length).split('#', 1).toString().split('&') + let queries = uri.substring(redirectUriPrefix.length).split('#', 1).toString().split('&') let queryMap = new Map() - querys.forEach(query => { - let arr = query.split('=') - queryMap.set(arr[0], decodeURI(arr[1])) + queries.forEach(query => { + const [name, value] = query.split('=') + queryMap.set(name, decodeURI(value)) }) ipcEvent.reply('MSALoginWindowReply', queryMap) @@ -143,13 +142,13 @@ ipcMain.on('openMSALoginWindow', (ipcEvent, args) => { }) MSALoginWindow.removeMenu() - MSALoginWindow.loadURL('https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=select_account&client_id=' + clientID + '&response_type=code&scope=XboxLive.signin%20offline_access&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient') + MSALoginWindow.loadURL('https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=select_account&client_id=' + CLIENT_ID + '&response_type=code&scope=XboxLive.signin%20offline_access&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient') }) -let MSALogoutWindow = null +let MSALogoutWindow -ipcMain.on('openMSALogoutWindow', (ipcEvent, args) => { - if (MSALogoutWindow == null) { +ipcMain.on('openMSALogoutWindow', (ipcEvent) => { + if (!MSALogoutWindow) { MSALogoutWindow = new BrowserWindow({ title: 'Microsoft Logout', backgroundColor: '#222222', @@ -158,12 +157,12 @@ ipcMain.on('openMSALogoutWindow', (ipcEvent, args) => { frame: true, icon: getPlatformIcon('SealCircle') }) + MSALogoutWindow.removeMenu() MSALogoutWindow.loadURL('https://login.microsoftonline.com/common/oauth2/v2.0/logout') - MSALogoutWindow.webContents.on('did-navigate', (e) => { + MSALogoutWindow.webContents.on('did-navigate', () => { setTimeout(() => { ipcEvent.reply('MSALogoutWindowReply') }, 5000) - }) } }) diff --git a/package-lock.json b/package-lock.json index 820fd6fc..b29ce582 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,68 @@ "sumchecker": "^3.0.1" }, "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -74,6 +136,40 @@ "universalify": "^0.1.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -83,6 +179,42 @@ "graceful-fs": "^4.1.6" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -215,18 +347,27 @@ } }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" }, "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "requires": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" } }, "@types/debug": { @@ -255,6 +396,19 @@ "@types/node": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "requires": { + "@types/node": "*" + } + }, "@types/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", @@ -265,8 +419,7 @@ "@types/node": { "version": "14.17.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", - "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", - "dev": true + "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==" }, "@types/plist": { "version": "3.0.2", @@ -279,6 +432,14 @@ "xmlbuilder": ">=11.0.1" } }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, "@types/semver": { "version": "7.3.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.6.tgz", @@ -757,36 +918,23 @@ "sax": "^1.2.4" } }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + }, "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" } }, "callsites": { @@ -922,7 +1070,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -1090,12 +1237,18 @@ } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "deep-extend": { @@ -1111,10 +1264,9 @@ "dev": true }, "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, "define-properties": { "version": "1.1.3", @@ -1932,10 +2084,9 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "requires": { "pump": "^3.0.0" } @@ -2050,22 +2201,21 @@ } }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" } }, "graceful-fs": { @@ -2116,8 +2266,7 @@ "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "http-signature": { "version": "1.2.0", @@ -2129,6 +2278,15 @@ "sshpk": "^1.7.0" } }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "iconv-corefoundation": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.6.tgz", @@ -2338,10 +2496,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "json-schema": { "version": "0.2.3", @@ -2394,12 +2551,11 @@ } }, "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", "requires": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "latest-version": { @@ -2461,10 +2617,9 @@ "dev": true }, "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "lru-cache": { "version": "6.0.0", @@ -2531,8 +2686,7 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -2586,10 +2740,9 @@ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm-conf": { "version": "1.1.3", @@ -2637,10 +2790,9 @@ } }, "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "package-json": { "version": "6.5.0", @@ -2654,6 +2806,138 @@ "semver": "^6.2.0" }, "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2786,6 +3070,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -2884,6 +3173,11 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, + "resolve-alpn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", + "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2891,12 +3185,11 @@ "dev": true }, "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "rimraf": { @@ -3616,9 +3909,9 @@ } }, "ws": { - "version": "7.5.2", + "version": "7.5.3", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.2.tgz", - "integrity": "sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ==" + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" }, "xdg-basedir": { "version": "4.0.0", diff --git a/package.json b/package.json index 579ab358..45b359bd 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "electron-updater": "^4.3.9", "fs-extra": "^10.0.0", "github-syntax-dark": "^0.5.0", + "got": "^11.8.2", "jquery": "^3.6.0", "request": "^2.88.2", "semver": "^7.3.5",