feat(#1094): deleting all cookies for a domain

This commit is contained in:
Anoop M D 2023-12-02 00:49:46 +05:30
parent 32c8bf296a
commit 752d4ae79e
6 changed files with 109 additions and 19 deletions

View File

@ -0,0 +1,16 @@
import styled from 'styled-components';
const Wrapper = styled.div`
table {
width: 100%;
table-layout: fixed;
thead {
color: ${(props) => props.theme.table.thead.color};
font-size: 0.8125rem;
user-select: none;
}
}
`;
export default Wrapper;

View File

@ -1,28 +1,52 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import Modal from 'components/Modal'; import Modal from 'components/Modal';
import { IconTrash } from '@tabler/icons';
import { deleteCookiesForDomain } from 'providers/ReduxStore/slices/app';
import toast from 'react-hot-toast';
import StyledWrapper from './StyledWrapper';
const CollectionProperties = ({ onClose }) => { const CollectionProperties = ({ onClose }) => {
const dispatch = useDispatch();
const cookies = useSelector((state) => state.app.cookies) || []; const cookies = useSelector((state) => state.app.cookies) || [];
const handleDeleteDomain = (domain) => {
dispatch(deleteCookiesForDomain(domain))
.then(() => {
toast.success('Domain deleted successfully');
})
.catch((err) => console.log(err) && toast.error('Failed to delete domain'));
};
return ( return (
<Modal size="md" title="Cookies" hideFooter={true} handleCancel={onClose}> <Modal size="md" title="Cookies" hideFooter={true} handleCancel={onClose}>
<StyledWrapper>
<table className="w-full border-collapse" style={{ marginTop: '-1rem' }}> <table className="w-full border-collapse" style={{ marginTop: '-1rem' }}>
<thead> <thead>
<tr> <tr>
<th className="py-2 px-2 text-left">Domain</th> <th className="py-2 px-2 text-left">Domain</th>
<th className="py-2 px-2 text-left">Cookie</th> <th className="py-2 px-2 text-left">Cookie</th>
<th className="py-2 px-2 text-center" style={{ width: 80 }}>
Actions
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{cookies.map((cookie) => ( {cookies.map((cookie) => (
<tr key={cookie.id}> <tr key={cookie.domain}>
<td className="py-2 px-2">{cookie.domain}</td> <td className="py-2 px-2">{cookie.domain}</td>
<td className="py-2 px-2 break-all">{cookie.cookieString}</td> <td className="py-2 px-2 break-all">{cookie.cookieString}</td>
<td className="text-center">
<button tabIndex="-1" onClick={() => handleDeleteDomain(cookie.domain)}>
<IconTrash strokeWidth={1.5} size={20} />
</button>
</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</StyledWrapper>
</Modal> </Modal>
); );
}; };

View File

@ -84,4 +84,12 @@ export const savePreferences = (preferences) => (dispatch, getState) => {
}); });
}; };
export const deleteCookiesForDomain = (domain) => (dispatch, getState) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;
ipcRenderer.invoke('renderer:delete-cookies-for-domain', domain).then(resolve).catch(reject);
});
};
export default appSlice.reducer; export default appSlice.reducer;

View File

@ -14,10 +14,10 @@ const {
searchForBruFiles, searchForBruFiles,
sanitizeDirectoryName sanitizeDirectoryName
} = require('../utils/filesystem'); } = require('../utils/filesystem');
const { stringifyJson } = require('../utils/common');
const { openCollectionDialog } = require('../app/collections'); const { openCollectionDialog } = require('../app/collections');
const { generateUidBasedOnHash } = require('../utils/common'); const { generateUidBasedOnHash, stringifyJson, safeParseJSON, safeStringifyJSON } = require('../utils/common');
const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids'); const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids');
const { deleteCookiesForDomain, getDomainsWithCookies } = require('../utils/cookies');
const EnvironmentSecretsStore = require('../store/env-secrets'); const EnvironmentSecretsStore = require('../store/env-secrets');
const environmentSecretsStore = new EnvironmentSecretsStore(); const environmentSecretsStore = new EnvironmentSecretsStore();
@ -511,6 +511,17 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
return Promise.reject(new Error('Failed to load GraphQL schema file')); return Promise.reject(new Error('Failed to load GraphQL schema file'));
} }
}); });
ipcMain.handle('renderer:delete-cookies-for-domain', async (event, domain) => {
try {
await deleteCookiesForDomain(domain);
const domainsWithCookies = await getDomainsWithCookies();
mainWindow.webContents.send('main:cookies-update', safeParseJSON(safeStringifyJSON(domainsWithCookies)));
} catch (error) {
return Promise.reject(error);
}
});
}; };
const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => { const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => {

View File

@ -25,6 +25,22 @@ const parseJson = async (obj) => {
} }
}; };
const safeStringifyJSON = (data) => {
try {
return JSON.stringify(data);
} catch (e) {
return data;
}
};
const safeParseJSON = (data) => {
try {
return JSON.parse(data);
} catch (e) {
return data;
}
};
const simpleHash = (str) => { const simpleHash = (str) => {
let hash = 0; let hash = 0;
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
@ -73,6 +89,8 @@ module.exports = {
uuid, uuid,
stringifyJson, stringifyJson,
parseJson, parseJson,
safeStringifyJSON,
safeParseJSON,
simpleHash, simpleHash,
generateUidBasedOnHash, generateUidBasedOnHash,
flattenDataForDotNotation flattenDataForDotNotation

View File

@ -64,9 +64,22 @@ const getDomainsWithCookies = () => {
}); });
}; };
const deleteCookiesForDomain = (domain) => {
return new Promise((resolve, reject) => {
cookieJar.store.removeCookies(domain, null, (err) => {
if (err) {
return reject(err);
}
return resolve();
});
});
};
module.exports = { module.exports = {
addCookieToJar, addCookieToJar,
getCookiesForUrl, getCookiesForUrl,
getCookieStringForUrl, getCookieStringForUrl,
getDomainsWithCookies getDomainsWithCookies,
deleteCookiesForDomain
}; };