Skip to content

Commit

Permalink
dissconnect-all-addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
salman-neslit committed Dec 6, 2024
1 parent 986f5fd commit f74717d
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ type AddressProps = {
type AddressDetailsProps = {
profile: NewProfile;
addressInfo: AddressInfo;
toggleRemoveModal: (val: boolean, address: AddressInfo) => void;
toggleRemoveModal: (
val: boolean,
address: AddressInfo,
isBulkDelete: boolean,
) => void;
};

type LinkedAddressesProps = {
Expand Down Expand Up @@ -67,7 +71,11 @@ const AddressDetails = (props: AddressDetailsProps) => {
menuItems={[
{
label: `Disconnect ${formatAddressShort(address)}`,
onClick: () => toggleRemoveModal(true, addressInfo),
onClick: () => toggleRemoveModal(true, addressInfo, false),
},
{
label: 'Delete All Addresses',
onClick: () => toggleRemoveModal(true, addressInfo, true),
},
]}
renderTrigger={(onclick) => (
Expand Down Expand Up @@ -98,6 +106,7 @@ export const LinkedAddresses = (props: LinkedAddressesProps) => {
const [currentAddress, setCurrentAddress] = useState<AddressInfo | null>(
null,
);
const [isBulkDelete, setIsBulkDelete] = useState(false);

const { profile, addresses, refreshProfiles } = props;

Expand All @@ -123,9 +132,11 @@ export const LinkedAddresses = (props: LinkedAddressesProps) => {
toggleRemoveModal={(
val: boolean,
selectedAddress: AddressInfo,
isBulkDelete: boolean = false,

Check failure on line 135 in packages/commonwealth/client/scripts/views/components/linked_addresses.tsx

View workflow job for this annotation

GitHub Actions / Code Quality Recommendations (22)

'isBulkDelete' is already declared in the upper scope on line 109 column 10
) => {
setIsRemoveModalOpen(val);
setCurrentAddress(selectedAddress);
setIsBulkDelete(isBulkDelete);
}}
/>
);
Expand Down Expand Up @@ -155,6 +166,7 @@ export const LinkedAddresses = (props: LinkedAddressesProps) => {
setIsRemoveModalOpen(false);
refreshProfiles(currentAddress);
}}
isBulkDelete={isBulkDelete}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ type DeleteAddressModalAttrs = {
address: AddressInfo;
chain: string;
closeModal: () => void;
isBulkDelete?: boolean;
};

export const DeleteAddressModal = ({
address,
addresses,
chain,
closeModal,
isBulkDelete = false,
}: DeleteAddressModalAttrs) => {
const user = useUserStore();

Expand All @@ -42,11 +44,13 @@ export const DeleteAddressModal = ({
}

try {
const response = await axios.post(`${SERVER_URL}/deleteAddress`, {
address: address.address,
chain,
jwt: user.jwt,
});
const payload = { address: address?.address, chain, jwt: user.jwt };

const endpoint = isBulkDelete
? `${SERVER_URL}/deleteAllAddresses`
: `${SERVER_URL}/deleteAddress`;

const response = await axios.post(endpoint, payload);

if (response?.data.status === 'Success') {
const updatedAddresses = [...user.addresses].filter(
Expand Down Expand Up @@ -87,15 +91,19 @@ export const DeleteAddressModal = ({
return (
<div className="DeleteAddressModal">
<CWModalHeader
label={`Disconnect ${formatAddressShort(address.address)}`}
label={
isBulkDelete
? 'Disconnect All Addresses'
: `Disconnect ${formatAddressShort(address?.address || '')}`
}
icon="danger"
onModalClose={closeModal}
/>
<CWModalBody>
<CWText>
By removing this address you will be leaving the{' '}
{address.community.id}. Your contributions and comments will remain.
Don&apos;t worry, you can rejoin anytime.
{isBulkDelete
? `By leaving ${address?.community.id} you will disconnect all linked addresses. Your threads will remain intact.`

Check warning on line 105 in packages/commonwealth/client/scripts/views/modals/delete_address_modal.tsx

View workflow job for this annotation

GitHub Actions / Code Quality Recommendations (22)

This line has a length of 126. Maximum allowed is 120
: `By removing this address you will be leaving the ${address?.community.id}. Your contributions and comments will remain. Don't worry, you can rejoin anytime.`}

Check warning on line 106 in packages/commonwealth/client/scripts/views/modals/delete_address_modal.tsx

View workflow job for this annotation

GitHub Actions / Code Quality Recommendations (22)

This line has a length of 173. Maximum allowed is 120
</CWText>
</CWModalBody>
<CWModalFooter>
Expand All @@ -106,7 +114,7 @@ export const DeleteAddressModal = ({
buttonHeight="sm"
/>
<CWButton
label="Disconnect Address"
label={isBulkDelete ? 'Disconnect All' : 'Disconnect Address'}
buttonType="destructive"
onClick={handleDelete}
buttonHeight="sm"
Expand Down
108 changes: 108 additions & 0 deletions packages/commonwealth/server/routes/deleteAllAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { AppError } from '@hicommonwealth/core';
import type { DB } from '@hicommonwealth/model';
import { decrementProfileCount } from '@hicommonwealth/model';
import { WalletId } from '@hicommonwealth/shared';
import type { NextFunction, Request, Response } from 'express';

export const Errors = {
NotLoggedIn: 'Not signed in',
NeedAddress: 'Must provide address',
NeedCommunity: 'Must provide community',
AddressNotFound: 'Address not found',
CannotDeleteMagic: 'Cannot delete Magic Link address',
CannotDeleteOnlyAdmin:
'Community must have at least 1 admin. Please assign another community member as admin, to leave this community.',
};

const deleteAllAddress = async (
models: DB,
req: Request,
res: Response,
next: NextFunction,
) => {
const { community } = req;

if (!req.user) {
return next(new AppError(Errors.NotLoggedIn));
}
if (!req.body.address) {
return next(new AppError(Errors.NeedAddress));
}
if (!community) {
return next(new AppError(Errors.NeedCommunity));
}

const addressObj = await models.Address.findOne({
where: {
community_id: community.id,
address: req.body.address,
user_id: req.user.id,
},
});
if (!addressObj) {
return next(new AppError(Errors.AddressNotFound));
}
if (addressObj.wallet_id === WalletId.Magic) {
return next(new AppError(Errors.CannotDeleteMagic));
}

const [AssociatedAddresses, adminUsers] = await Promise.all([
models.Address.findAll({
where: {
user_id: addressObj.user_id,
community_id: addressObj.community_id,
},
}),
models.Address.findAll({
where: {
community_id: community.id,
role: 'admin',
},
}),
]);

if (
AssociatedAddresses.some(
(associatedAddress) =>
associatedAddress.dataValues.wallet_id === WalletId.Magic,
)
) {
return next(new AppError(Errors.CannotDeleteMagic));
}

if (
adminUsers.length === 1 &&
adminUsers.some((adminUser) =>
AssociatedAddresses.some(
(associatedAddress) =>
adminUser.dataValues.address === associatedAddress.dataValues.address,
),
)
) {
return next(new AppError(Errors.CannotDeleteOnlyAdmin));
}

await models.sequelize.transaction(async (transaction) => {
const associatedAddressIds = AssociatedAddresses.map(
(address) => address.dataValues.id,
).filter((id): id is number => id !== undefined);

if (associatedAddressIds.length > 0) {
await models.Address.update(
{ user_id: null, verified: null },
{
where: {
id: associatedAddressIds,
},
transaction,
},
);
}

await decrementProfileCount(community.id!, req.user!.id!, transaction);
});

return res.json({ status: 'Success', response: 'Deleted Address' });
};

export default deleteAllAddress;
9 changes: 9 additions & 0 deletions packages/commonwealth/server/routing/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import { ServerTagsController } from 'server/controllers/server_tags_controller'
import { rateLimiterMiddleware } from 'server/middleware/rateLimiter';
import { getTopUsersHandler } from 'server/routes/admin/get_top_users_handler';
import { getNamespaceMetadata } from 'server/routes/communities/get_namespace_metadata';
import deleteAllAddress from 'server/routes/deleteAllAddress';
import { config } from '../config';
import { getStatsHandler } from '../routes/admin/get_stats_handler';
import { getCanvasClockHandler } from '../routes/canvas/get_canvas_clock_handler';
Expand Down Expand Up @@ -176,6 +177,14 @@ function setupRouter(
databaseValidationService.validateCommunity,
deleteAddress.bind(this, models),
);
registerRoute(
router,
'post',
'/deleteAllAddresses',
passport.authenticate('jwt', { session: false }),
databaseValidationService.validateCommunity,
deleteAllAddress.bind(this, models),
);
registerRoute(
router,
'post',
Expand Down

0 comments on commit f74717d

Please sign in to comment.