From f2ff04fa04c73dbac671bb92b4718240d036a650 Mon Sep 17 00:00:00 2001 From: Tanmoy Basak Anjan Date: Mon, 24 Jun 2024 22:49:26 +0600 Subject: [PATCH] Feat/2271 blacklisted banner (#2272) * updating packages * bucket id added * blacklisted banners * context fixed * banner updates * lingui extract removed * blacklisting work * account blacklisted --- .github/workflows/lingui-extract-files.yml | 39 --------------- .github/workflows/lingui-extract-storage.yml | 40 ---------------- .../Elements/BlacklistedModeBanner.tsx | 48 +++++++++++++++++++ .../src/Components/Elements/BucketRow.tsx | 41 ++++++++++++++-- .../src/Components/Layouts/AppNav.tsx | 1 - .../src/Components/Layouts/AppWrapper.tsx | 2 +- .../Modules/FilesList/FilesList.tsx | 8 ++-- .../src/Components/Pages/BucketsPage.tsx | 24 +++++++--- .../src/Components/Pages/CidsPage.tsx | 8 ++-- .../src/Contexts/StorageApiContext.tsx | 21 +++++--- .../storage-ui/src/locales/en/messages.po | 12 +++++ yarn.lock | 6 +-- 12 files changed, 142 insertions(+), 108 deletions(-) delete mode 100644 .github/workflows/lingui-extract-files.yml delete mode 100644 .github/workflows/lingui-extract-storage.yml create mode 100644 packages/storage-ui/src/Components/Elements/BlacklistedModeBanner.tsx diff --git a/.github/workflows/lingui-extract-files.yml b/.github/workflows/lingui-extract-files.yml deleted file mode 100644 index 4c4b28c631..0000000000 --- a/.github/workflows/lingui-extract-files.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Lingui extract - Files -on: - pull_request: - branches: - - "dev" - paths: - - "packages/files-ui/**/*" -jobs: - # extract any new translatable string - # and commit if there are new ones - # and if the user submitting the PR isn't weblate - extract: - name: lingui-extract - runs-on: ubuntu-latest - if: ${{ github.actor != 'weblate' }} - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.ref }} - ssh-key: ${{ secrets.LINGUI_GH_ACTION_COMMIT_KEY }} - - name: set user - run: | - git config --global user.name 'GitHub Actions' - git config --global user.email 'actions@github.com' - - # use node module caching - - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - - - name: install packages - run: yarn install --immutable - - - name: lingui-extract and commit - run: | - (cd packages/files-ui && yarn extract --clean) - git add packages/files-ui/src/locales/* - if git commit -m "lingui extract"; then git push; else echo 'exiting successfully without commit'; fi diff --git a/.github/workflows/lingui-extract-storage.yml b/.github/workflows/lingui-extract-storage.yml deleted file mode 100644 index ada3fc6491..0000000000 --- a/.github/workflows/lingui-extract-storage.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Lingui extract - Storage -on: - pull_request: - branches: - - "dev" - paths: - - "packages/storage-ui/**/*" -jobs: - # extract any new translatable string - # and commit if there are new ones - # and if the user submitting the PR isn't weblate - extract: - name: lingui-extract - runs-on: ubuntu-latest - if: ${{ github.actor != 'weblate' }} - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.ref }} - ssh-key: ${{ secrets.LINGUI_GH_ACTION_COMMIT_KEY }} - - name: set user - run: | - git config --global user.name 'GitHub Actions' - git config --global user.email 'actions@github.com' - - # use node module caching - - uses: actions/cache@v2 - with: - path: '**/node_modules' - key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - - - name: install packages - run: yarn install --immutable - - - name: lingui-extract and commit - if: ${{ github.actor != 'weblate' }} - run: | - (cd packages/storage-ui && yarn extract --clean) - git add packages/storage-ui/src/locales/* - if git commit -m "lingui extract"; then git push; else echo 'exiting successfully without commit'; fi diff --git a/packages/storage-ui/src/Components/Elements/BlacklistedModeBanner.tsx b/packages/storage-ui/src/Components/Elements/BlacklistedModeBanner.tsx new file mode 100644 index 0000000000..f8041d9007 --- /dev/null +++ b/packages/storage-ui/src/Components/Elements/BlacklistedModeBanner.tsx @@ -0,0 +1,48 @@ +import { Typography, Button } from "@chainsafe/common-components" +import { createStyles, makeStyles, useThemeSwitcher } from "@chainsafe/common-theme" +import { Trans } from "@lingui/macro" +import React from "react" +import { CSSTheme } from "../../Themes/types" +import { ROUTE_LINKS } from "../StorageRoutes" + +const useStyles = makeStyles( + ({ breakpoints, constants, palette }: CSSTheme) => { + return createStyles({ + accountRestrictedNotification: { + position: "fixed", + bottom: 0, + backgroundColor: palette.additional["gray"][10], + color: palette.additional["gray"][1], + padding: `${constants.generalUnit * 2}px ${constants.generalUnit * 3}px`, + left: 0, + width: "100vw", + [breakpoints.up("md")]: { + left: `${constants.navWidth}px`, + width:`calc(100vw - ${constants.navWidth}px)`, + display: "flex", + justifyContent: "space-between", + alignItems: "center" + } + } + }) + } +) + +const BlacklistedModeBanner = () => { + const classes = useStyles() + const { desktop } = useThemeSwitcher() + + return ( +
+ + Your account has been blacklisted due to unusual activity + + +
) +} + +export default BlacklistedModeBanner \ No newline at end of file diff --git a/packages/storage-ui/src/Components/Elements/BucketRow.tsx b/packages/storage-ui/src/Components/Elements/BucketRow.tsx index ae341621c9..0b219c9286 100644 --- a/packages/storage-ui/src/Components/Elements/BucketRow.tsx +++ b/packages/storage-ui/src/Components/Elements/BucketRow.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useMemo, useRef, useState, useCallback } from "react" -import { makeStyles, createStyles, useOnClickOutside } from "@chainsafe/common-theme" +import { makeStyles, createStyles, useOnClickOutside, useThemeSwitcher } from "@chainsafe/common-theme" import { + CopyIcon, DeleteSvg, EditSvg, formatBytes, @@ -12,7 +13,8 @@ import { TableCell, TableRow, Typography, - useHistory + useHistory, + useToasts } from "@chainsafe/common-components" import { t, Trans } from "@lingui/macro" import { Bucket } from "@chainsafe/files-api-client" @@ -23,7 +25,7 @@ import clsx from "clsx" import { Form, FormikProvider, useFormik } from "formik" import { nameValidator } from "../../Utils/validationSchema" -const useStyles = makeStyles(({ animation, constants, breakpoints }: CSSTheme) => +const useStyles = makeStyles(({ palette, animation, constants, breakpoints }: CSSTheme) => createStyles({ dropdownIcon: { "& svg": { @@ -93,6 +95,15 @@ const useStyles = makeStyles(({ animation, constants, breakpoints }: CSSTheme) = [breakpoints.down("md")]: { margin: `${constants.generalUnit * 4.2}px 0` } + }, + idRow: { + display: "flex", + alignItems: "center" + }, + copyIcon: { + fontSize: "16px", + fill: palette.additional["gray"][8], + marginLeft: "8px" } }) ) @@ -106,6 +117,9 @@ interface Props { const BucketRow = ({ bucket, onRemoveBucket, handleContextMenu, handleRename }: Props) => { const classes = useStyles() const { redirect } = useHistory() + const { addToast } = useToasts() + const { desktop } = useThemeSwitcher() + const menuItems = useMemo(() => [ { contents: ( @@ -168,6 +182,14 @@ const BucketRow = ({ bucket, onRemoveBucket, handleContextMenu, handleRename }: useOnClickOutside(formRef, formik.submitForm) + const onCopyBucketId = () => { + navigator.clipboard.writeText(bucket.id) + addToast({ + title: t`Bucket Id copied`, + type: "success" + }) + } + return ( + {desktop && + + {bucket.id } + + + } diff --git a/packages/storage-ui/src/Components/Layouts/AppNav.tsx b/packages/storage-ui/src/Components/Layouts/AppNav.tsx index d6e3fb80d4..2e21d076cf 100644 --- a/packages/storage-ui/src/Components/Layouts/AppNav.tsx +++ b/packages/storage-ui/src/Components/Layouts/AppNav.tsx @@ -18,7 +18,6 @@ import { useLocation, KeySvg, CreditCardOutlinedSvg - // FileWithImageSvg } from "@chainsafe/common-components" import { ROUTE_LINKS } from "../StorageRoutes" import { Trans } from "@lingui/macro" diff --git a/packages/storage-ui/src/Components/Layouts/AppWrapper.tsx b/packages/storage-ui/src/Components/Layouts/AppWrapper.tsx index 01e82bdbd5..77eea750f2 100644 --- a/packages/storage-ui/src/Components/Layouts/AppWrapper.tsx +++ b/packages/storage-ui/src/Components/Layouts/AppWrapper.tsx @@ -3,7 +3,7 @@ import React, { useState } from "react" import { ReactNode } from "react" import clsx from "clsx" import { useStorageApi } from "../../Contexts/StorageApiContext" -import { CssBaseline } from "@chainsafe/common-components" +import { CssBaseline } from "@chainsafe/common-components" import AppHeader from "./AppHeader" import AppNav from "./AppNav" diff --git a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx index 41a87701ae..19139fa8a0 100644 --- a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx +++ b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx @@ -44,6 +44,7 @@ import { ISelectedFile, useFileBrowser } from "../../../Contexts/FileBrowserCont import SurveyBanner from "../SurveyBanner" import { useStorageApi } from "../../../Contexts/StorageApiContext" import RestrictedModeBanner from "../../Elements/RestrictedModeBanner" +import BlacklistedModeBanner from "../../Elements/BlacklistedModeBanner" import { DragPreviewLayer } from "./DragPreviewLayer" import FolderBreadcrumb from "./FolderBreadcrumb" import { DragTypes } from "./DragConstants" @@ -326,7 +327,7 @@ const sortFoldersFirst = (a: FileSystemItemType, b: FileSystemItemType) => const FilesList = () => { const { themeKey, desktop } = useThemeSwitcher() - const { accountRestricted } = useStorageApi() + const { accountRestricted, accountBlacklisted } = useStorageApi() const { heading, controls = true, @@ -1212,9 +1213,8 @@ const FilesList = () => { ) } - {accountRestricted && - - } + {accountRestricted && } + {accountBlacklisted && } ) } diff --git a/packages/storage-ui/src/Components/Pages/BucketsPage.tsx b/packages/storage-ui/src/Components/Pages/BucketsPage.tsx index 9940493378..747ebf734b 100644 --- a/packages/storage-ui/src/Components/Pages/BucketsPage.tsx +++ b/packages/storage-ui/src/Components/Pages/BucketsPage.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useState } from "react" -import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { makeStyles, createStyles, useThemeSwitcher } from "@chainsafe/common-theme" import { Button, Dialog, @@ -30,9 +30,10 @@ import { usePageTrack } from "../../Contexts/PosthogContext" import { Bucket, FileSystemType } from "@chainsafe/files-api-client" import { Helmet } from "react-helmet-async" import AnchorMenu, { AnchorMenuPosition } from "../UI-components/AnchorMenu" +import BlacklistedModeBanner from "../Elements/BlacklistedModeBanner" -export const desktopGridSettings = "3fr 150px 150px 70px !important" -export const mobileGridSettings = "3fr 100px 100px 70px !important" +export const desktopGridSettings = "2fr 5fr 150px 150px 50px !important" +export const mobileGridSettings = "1fr 150px 110px 50px !important" const useStyles = makeStyles(({ breakpoints, animation, constants, typography }: CSSTheme) => createStyles({ @@ -127,7 +128,7 @@ type SortDirection = "ascend" | "descend" const BucketsPage = () => { const classes = useStyles() const { storageBuckets, createBucket, refreshBuckets, removeBucket, editBucket } = useStorage() - const { accountRestricted } = useStorageApi() + const { accountRestricted, accountBlacklisted } = useStorageApi() const [isCreateBucketModalOpen, setIsCreateBucketModalOpen] = useState(false) const [bucketToRemove, setBucketToRemove] = useState() const [isRemovingBucket, setIsRemovingBucket] = useState(false) @@ -136,6 +137,8 @@ const BucketsPage = () => { const [sortColumn, setSortColumn] = useState(undefined) const [sortDirection, setSortDirection] = useState("descend") + const { desktop } = useThemeSwitcher() + const generalContextMenuOptions: IMenuItem[] = useMemo(() => [ { contents: ( @@ -317,6 +320,14 @@ const BucketsPage = () => { > Name + {desktop && + + Bucket Id + + } { )} - {accountRestricted && - - } + {accountRestricted && } + {accountBlacklisted && } { isLoadingPins, resetPins } = useStorage() - const { accountRestricted } = useStorageApi() + const { accountRestricted, accountBlacklisted } = useStorageApi() const [addCIDOpen, setAddCIDOpen] = useState(false) const [sortColumn, setSortColumn] = useState("date_uploaded") const [sortDirection, setSortDirection] = useState("descend") @@ -294,9 +295,8 @@ const CidsPage = () => { close={() => setAddCIDOpen(false)} modalOpen={addCIDOpen} /> - {accountRestricted && - - } + {accountRestricted && } + {accountBlacklisted && } ) } diff --git a/packages/storage-ui/src/Contexts/StorageApiContext.tsx b/packages/storage-ui/src/Contexts/StorageApiContext.tsx index 90f39a6b3a..8ac0e56bb6 100644 --- a/packages/storage-ui/src/Contexts/StorageApiContext.tsx +++ b/packages/storage-ui/src/Contexts/StorageApiContext.tsx @@ -70,6 +70,7 @@ type StorageApiContext = { status: DirectAuthContextStatus resetStatus(): void accountRestricted?: boolean + accountBlacklisted?: boolean } const StorageApiContext = React.createContext(undefined) @@ -105,6 +106,7 @@ const StorageApiProvider = ({ apiUrl, withLocalStorage = true, children }: Stora { exp: number; enckey?: string; mps?: string; uuid: string } | undefined >(undefined) const [accountRestricted, setAccountRestricted] = useState(false) + const [accountBlacklisted, setAccountBlacklisted] = useState(false) // returning user const isReturningUserLocal = localStorageGet(isReturningUserStorageKey) @@ -234,7 +236,7 @@ const StorageApiProvider = ({ apiUrl, withLocalStorage = true, children }: Stora useEffect(() => { if (accessToken && accessToken.token && storageApiClient) { storageApiClient?.setToken(accessToken.token) - const decodedAccessToken = jwtDecode<{ perm: { secured?: string; files?: string } }>( + const decodedAccessToken = jwtDecode<{ perm: { secured?: string; files?: string; storage?: string } }>( accessToken.token ) @@ -243,6 +245,12 @@ const StorageApiProvider = ({ apiUrl, withLocalStorage = true, children }: Stora } else { setAccountRestricted(false) } + + if (decodedAccessToken.perm.storage === "blacklisted") { + setAccountBlacklisted(true) + } else { + setAccountBlacklisted(false) + } } }, [accessToken, storageApiClient]) @@ -263,14 +271,14 @@ const StorageApiProvider = ({ apiUrl, withLocalStorage = true, children }: Stora } } + useEffect(() => { - if (refreshToken && refreshToken.token) { + if (refreshToken?.token) { try { - const decoded = jwtDecode<{ mps?: string; enckey?: string; exp: number; uuid: string }>( + const decodedRefresh = jwtDecode<{ mps?: string; enckey?: string; exp: number; uuid: string }>( refreshToken.token ) - - setDecodedRefreshToken(decoded) + setDecodedRefreshToken(decodedRefresh) } catch (error) { console.error("Error decoding access token") } @@ -422,7 +430,8 @@ const StorageApiProvider = ({ apiUrl, withLocalStorage = true, children }: Stora selectWallet, resetAndSelectWallet, logout, - accountRestricted + accountRestricted, + accountBlacklisted }} > {children} diff --git a/packages/storage-ui/src/locales/en/messages.po b/packages/storage-ui/src/locales/en/messages.po index 478ccd6684..373ebfd851 100644 --- a/packages/storage-ui/src/locales/en/messages.po +++ b/packages/storage-ui/src/locales/en/messages.po @@ -118,6 +118,12 @@ msgstr "Billing start time" msgid "Browse files" msgstr "Browse files" +msgid "Bucket Id" +msgstr "Bucket Id" + +msgid "Bucket Id copied" +msgstr "Bucket Id copied" + msgid "Bucket name" msgstr "Bucket name" @@ -274,6 +280,9 @@ msgstr "Destination Address" msgid "Didn't receive the email ?" msgstr "Didn't receive the email ?" +msgid "Discord support" +msgstr "Discord support" + msgid "Docs" msgstr "Docs" @@ -805,6 +814,9 @@ msgstr "You will need to sign a message in your wallet to complete sign in." msgid "You've got a payment due. Until you've settled up, we've placed your account in restricted mode" msgstr "You've got a payment due. Until you've settled up, we've placed your account in restricted mode" +msgid "Your account has been blacklisted due to unusual activity" +msgstr "Your account has been blacklisted due to unusual activity" + msgid "Your account is restricted. Until you've settled up, you can't upload any new content." msgstr "Your account is restricted. Until you've settled up, you can't upload any new content." diff --git a/yarn.lock b/yarn.lock index 3c6be51480..bfa88d87bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9929,9 +9929,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001251: - version "1.0.30001414" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz" - integrity sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg== + version "1.0.30001621" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz" + integrity sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA== capture-exit@^2.0.0: version "2.0.0"