├── .env ├── server ├── python │ ├── .gitignore │ ├── requirements.txt │ └── app.py └── go │ └── go.mod ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json └── index.html ├── src ├── assets │ ├── Union.png │ ├── favicon.ico │ ├── search.png │ ├── help-icon.png │ ├── Union-yellow.png │ ├── auth-background.png │ ├── edit-login-method.png │ ├── provider-bitbucket.png │ ├── delete-login-method.png │ ├── unlink-login-method.png │ ├── auth-background-portrait.png │ ├── triangle-down.svg │ ├── cross.svg │ ├── spinner.svg │ ├── checkmark-yellow.svg │ ├── provider-active-directory.svg │ ├── provider-facebook.svg │ ├── hamburger-menu.svg │ ├── arrow-down.svg │ ├── people.svg │ ├── chevron-right.svg │ ├── chevron-down.svg │ ├── chevron-left.svg │ ├── chevron-up-selected.svg │ ├── trash.svg │ ├── edit.svg │ ├── left-arrow-dark.svg │ ├── people-opened.svg │ ├── right_arrow_icon.svg │ ├── provider-gitlab.svg │ ├── copy.svg │ ├── close-icon.svg │ ├── close.svg │ ├── star_sparkle.svg │ ├── loader.svg │ ├── checkmark.svg │ ├── trash-opened.svg │ ├── auth-provider.svg │ ├── eye.svg │ ├── delete.svg │ ├── envelope-green.svg │ ├── provider-twitter.svg │ ├── lock-opened.svg │ ├── mail.svg │ ├── provider-github.svg │ ├── eye-stroke.svg │ ├── people-restricted.svg │ ├── form-field-error-icon.svg │ ├── mail-opened.svg │ ├── no-users-graphic.svg │ ├── phone-no.svg │ ├── provider-google.svg │ ├── provider-linkedin.svg │ ├── edit-unfilled.svg │ ├── provider-discord.svg │ ├── clear.svg │ ├── close-active.svg │ ├── close-inactive.svg │ ├── green-check.svg │ ├── plus.svg │ ├── tenant-management.svg │ ├── checkmark-green.svg │ ├── lock.svg │ ├── user-managment.svg │ ├── email.svg │ ├── info-icon.svg │ ├── provider-apple.svg │ └── help-circle.svg ├── ui │ ├── components │ │ ├── userroles │ │ │ ├── types.ts │ │ │ └── components │ │ │ │ ├── dialogs │ │ │ │ ├── deleteRole.scss │ │ │ │ ├── createNewRole.scss │ │ │ │ ├── editRole.scss │ │ │ │ └── AssignRoleConfimation.tsx │ │ │ │ ├── NoRolesFound.tsx │ │ │ │ ├── noRolesFound.scss │ │ │ │ └── rolesTable.scss │ │ ├── auth │ │ │ ├── types.ts │ │ │ ├── SignOutBtn.scss │ │ │ ├── SignInContentWrapper.tsx │ │ │ └── SignOutBtn.tsx │ │ ├── common │ │ │ ├── iconButton │ │ │ │ ├── style.scss │ │ │ │ └── index.tsx │ │ │ └── modals │ │ │ │ ├── TenantIdModals.scss │ │ │ │ └── TenantIdModals.tsx │ │ ├── shimmer │ │ │ ├── index.tsx │ │ │ └── shimmer.scss │ │ ├── userDetail │ │ │ ├── loginMethods │ │ │ │ └── components │ │ │ │ │ ├── editableInput.scss │ │ │ │ │ ├── editableInput.tsx │ │ │ │ │ ├── dropdown.scss │ │ │ │ │ └── dropDown.tsx │ │ │ ├── userRoles │ │ │ │ ├── UserRolesListHeader.tsx │ │ │ │ └── userRolesList.scss │ │ │ ├── tenantList │ │ │ │ ├── UserTenantsList.scss │ │ │ │ └── UserTenantsList.tsx │ │ │ ├── userDetailForm.scss │ │ │ └── components │ │ │ │ └── nameField │ │ │ │ └── nameField.tsx │ │ ├── select │ │ │ ├── select.scss │ │ │ └── index.tsx │ │ ├── tenants │ │ │ ├── tenantsListTable │ │ │ │ └── tenantsListTable.scss │ │ │ ├── noTenants │ │ │ │ ├── noTenants.scss │ │ │ │ └── NoTenants.tsx │ │ │ ├── creatNewTenant │ │ │ │ └── createNewTenant.scss │ │ │ └── tenantDetail │ │ │ │ ├── thirdPartyPage │ │ │ │ └── thirdPartyPage.scss │ │ │ │ ├── deleteThirdPartyClient │ │ │ │ └── deleteThirdPartyClient.scss │ │ │ │ ├── deleteTenant │ │ │ │ └── deleteTenant.scss │ │ │ │ ├── deleteThirdPartyProvider │ │ │ │ └── deleteThirdPartyProvider.scss │ │ │ │ ├── uneditablePropertyDialog │ │ │ │ └── UneditablePropertyDialog.tsx │ │ │ │ ├── thirdPartyProviderButton │ │ │ │ └── thirdPartyProviderButton.scss │ │ │ │ ├── tenantDetailPanel │ │ │ │ └── tenantDetailPanel.scss │ │ │ │ ├── addNewProviderDialog │ │ │ │ └── AddNewProviderDialog.tsx │ │ │ │ ├── TenantDetailContext.tsx │ │ │ │ ├── thirdPartyProviderInput │ │ │ │ └── thirdPartyProviderInput.scss │ │ │ │ └── editPluginPropertyDialog │ │ │ │ └── editPluginPropertyDialog.scss │ │ ├── layout │ │ │ ├── layoutPanel.tsx │ │ │ └── accessDeniedModal.tsx │ │ ├── collapsible │ │ │ └── collapsible.scss │ │ ├── deleteCrossButton │ │ │ ├── deleteCrossButton.scss │ │ │ └── DeleteCrossButton.tsx │ │ ├── checkbox │ │ │ ├── checkbox.scss │ │ │ └── Checkbox.tsx │ │ ├── pagination │ │ │ └── pagination.scss │ │ ├── loader │ │ │ ├── Loader.tsx │ │ │ └── loader.scss │ │ ├── alert │ │ │ └── index.tsx │ │ ├── errorBlock │ │ │ ├── ErrorBlock.tsx │ │ │ └── errorBlock.scss │ │ ├── errorboundary │ │ │ └── error-boundary.scss │ │ ├── badge │ │ │ └── index.tsx │ │ ├── recipePill │ │ │ ├── RecipePill.tsx │ │ │ └── recipePill.scss │ │ ├── inputField │ │ │ └── tagsInputField.scss │ │ ├── searchInput │ │ │ ├── SearchInput.tsx │ │ │ └── searchInput.scss │ │ ├── footer │ │ │ ├── footer.scss │ │ │ └── footer.tsx │ │ ├── sidebar │ │ │ └── sidebar.scss │ │ ├── createUser │ │ │ └── createUserDialog.scss │ │ ├── toggle │ │ │ └── Toggle.tsx │ │ ├── noUsers │ │ │ ├── NoUsers.css │ │ │ └── NoUsers.tsx │ │ ├── phoneNumber │ │ │ └── PhoneNumber.tsx │ │ ├── safeAreaView │ │ │ └── SafeAreaView.tsx │ │ ├── button │ │ │ └── index.tsx │ │ ├── copyText │ │ │ └── CopyText.scss │ │ ├── info-connection │ │ │ └── info-connection.tsx │ │ ├── nativeSelect │ │ │ ├── NativeSelect.tsx │ │ │ └── nativeSelect.scss │ │ └── authWrapper │ │ │ └── index.tsx │ ├── layouts │ │ ├── mainLayout.scss │ │ └── mainLayout.tsx │ ├── styles │ │ ├── index.ts │ │ └── mixin.scss │ ├── contexts │ │ └── AppEnvContext.tsx │ └── pages │ │ ├── userroles │ │ └── index.scss │ │ └── tenants │ │ └── index.scss ├── utils │ ├── customErrors.ts │ ├── user.ts │ └── form.ts ├── api │ ├── search │ │ └── searchTags.ts │ ├── user │ │ ├── email │ │ │ └── verify │ │ │ │ ├── token.ts │ │ │ │ └── index.ts │ │ ├── unlink.ts │ │ ├── delete.ts │ │ ├── password │ │ │ └── reset │ │ │ │ └── index.ts │ │ ├── sessions.ts │ │ └── metadata.ts │ ├── index.ts │ └── users │ │ └── count.ts ├── version.ts ├── types.ts ├── setupTests.ts ├── events │ └── accessDenied.ts ├── App.test.tsx ├── services │ └── storage.ts ├── reportWebVitals.ts ├── index.tsx └── react-app-env.d.ts ├── .vscode ├── extensions.json ├── copyright.code-snippets └── settings.json ├── .prettierignore ├── config ├── webpack │ └── persistentCache │ │ └── createEnvironmentHash.js └── jest │ ├── cssTransform.js │ ├── babelTransform.js │ └── fileTransform.js ├── .prettierrc ├── .gitignore ├── README.md ├── .github └── workflows │ ├── lint-pr-title.yml │ ├── github-actions-changelog.yml │ └── pre-commit-hook-run.yml ├── tsconfig.json └── scripts └── test.js /.env: -------------------------------------------------------------------------------- 1 | DISABLE_ESLINT_PLUGIN=true -------------------------------------------------------------------------------- /server/python/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/assets/Union.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/Union.png -------------------------------------------------------------------------------- /src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/favicon.ico -------------------------------------------------------------------------------- /src/assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/search.png -------------------------------------------------------------------------------- /src/ui/components/userroles/types.ts: -------------------------------------------------------------------------------- 1 | export type Role = { role: string; permissions: string[] }; 2 | -------------------------------------------------------------------------------- /src/assets/help-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/help-icon.png -------------------------------------------------------------------------------- /src/ui/components/auth/types.ts: -------------------------------------------------------------------------------- 1 | export type ContentMode = "sign-in" | "sign-up" | "forgot-password"; 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /src/assets/Union-yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/Union-yellow.png -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # testing 2 | /coverage 3 | 4 | # production 5 | /debug 6 | /build 7 | 8 | # static files 9 | /public -------------------------------------------------------------------------------- /server/python/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.0.1 2 | flask_cors==3.0.10 3 | python-dotenv==0.19.2 4 | # supertokens-python -------------------------------------------------------------------------------- /src/assets/auth-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/auth-background.png -------------------------------------------------------------------------------- /src/assets/edit-login-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/edit-login-method.png -------------------------------------------------------------------------------- /src/assets/provider-bitbucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/provider-bitbucket.png -------------------------------------------------------------------------------- /src/assets/delete-login-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/delete-login-method.png -------------------------------------------------------------------------------- /src/assets/unlink-login-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/unlink-login-method.png -------------------------------------------------------------------------------- /src/assets/auth-background-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertokens/dashboard/HEAD/src/assets/auth-background-portrait.png -------------------------------------------------------------------------------- /src/ui/components/common/iconButton/style.scss: -------------------------------------------------------------------------------- 1 | @import "../../../styles/mixin.scss"; 2 | 3 | .button-root { 4 | cursor: pointer; 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/triangle-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/cross.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/assets/checkmark-yellow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/shimmer/index.tsx: -------------------------------------------------------------------------------- 1 | import "./shimmer.scss"; 2 | 3 | type ShimmerProps = { 4 | className?: string; 5 | }; 6 | 7 | export default function Shimmer({ className }: ShimmerProps) { 8 | return
; 9 | } 10 | -------------------------------------------------------------------------------- /config/webpack/persistentCache/createEnvironmentHash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const { createHash } = require('crypto'); 3 | 4 | module.exports = env => { 5 | const hash = createHash('md5'); 6 | hash.update(JSON.stringify(env)); 7 | 8 | return hash.digest('hex'); 9 | }; 10 | -------------------------------------------------------------------------------- /src/ui/components/shimmer/shimmer.scss: -------------------------------------------------------------------------------- 1 | .shimmer { 2 | width: 100%; 3 | background-color: var(--color-loader-placeholder-bg); 4 | min-height: 1em; 5 | opacity: 0.4; 6 | animation: blinker 2s linear infinite; 7 | @keyframes blinker { 8 | 50% { 9 | opacity: 0.1; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/utils/customErrors.ts: -------------------------------------------------------------------------------- 1 | export class ForbiddenError extends Error { 2 | statusCode = 403; 3 | status = "FORBIDDEN_REQUEST"; 4 | constructor(message: string) { 5 | super(message); 6 | } 7 | 8 | static isThisError(err: any): boolean { 9 | return err.status === "FORBIDDEN_REQUEST"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/dialogs/deleteRole.scss: -------------------------------------------------------------------------------- 1 | .you-sure-text { 2 | color: #000; 3 | font-size: 14px; 4 | font-style: normal; 5 | font-weight: 400; 6 | line-height: 23px; 7 | padding-top: 24px; 8 | 9 | .red { 10 | color: var(--color-button-error); 11 | font-weight: 600; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/assets/provider-active-directory.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true, 4 | "semi": true, 5 | "bracketSpacing": true, 6 | "singleQuote": false, 7 | "trailingComma": "es5", 8 | "arrowParens": "always", 9 | "jsxBracketSameLine": true, 10 | "bracketSameLine": true, 11 | "singleAttributePerLine": true, 12 | "printWidth": 120 13 | } 14 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/loginMethods/components/editableInput.scss: -------------------------------------------------------------------------------- 1 | .input { 2 | display: flex; 3 | justify-content: flex-start; 4 | align-items: baseline; 5 | 6 | @media (max-width: 340px) { 7 | flex-direction: column; 8 | } 9 | } 10 | 11 | .input-field-container { 12 | margin-bottom: 0 !important; 13 | } 14 | -------------------------------------------------------------------------------- /src/ui/components/select/select.scss: -------------------------------------------------------------------------------- 1 | .st-select { 2 | outline: none; 3 | 4 | width: 210px; 5 | height: 36px; 6 | padding: 9px 13px; 7 | 8 | border-radius: 6px; 9 | border: 1px solid #e5e5e5; 10 | background: #fff; 11 | 12 | color: #222; 13 | font-size: 14px; 14 | font-style: normal; 15 | font-weight: 400; 16 | line-height: normal; 17 | } 18 | -------------------------------------------------------------------------------- /src/assets/provider-facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ui/components/auth/SignOutBtn.scss: -------------------------------------------------------------------------------- 1 | button#sign-out-btn { 2 | position: absolute; 3 | top: 24px; 4 | right: 60px; 5 | background: var(--color-white); 6 | border: 1px solid var(--color-black); 7 | border-radius: 6px; 8 | padding: 6px 8px; 9 | font-size: 14px; 10 | font-family: inherit; 11 | line-height: 17px; 12 | font-weight: 500; 13 | cursor: pointer; 14 | z-index: 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/ui/layouts/mainLayout.scss: -------------------------------------------------------------------------------- 1 | .main-layout-container { 2 | display: block; 3 | 4 | .main-content { 5 | margin-top: 44px; 6 | margin-left: var(--sidebar-width); 7 | padding: 0 20px; 8 | min-height: 100vh; 9 | } 10 | } 11 | 12 | @media (max-width: 1024px) { 13 | .main-layout-container { 14 | .main-content { 15 | margin-left: 0; 16 | padding: 0; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/assets/hamburger-menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/people.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /debug 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .idea 25 | -------------------------------------------------------------------------------- /src/assets/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantsListTable/tenantsListTable.scss: -------------------------------------------------------------------------------- 1 | .tenant-id-column { 2 | width: 20% !important; 3 | } 4 | 5 | .tenant-list-table-pagination { 6 | justify-content: flex-end; 7 | padding: 24px; 8 | } 9 | 10 | .tenant-login-methods { 11 | display: flex; 12 | gap: 10px; 13 | } 14 | 15 | .tenant-no-login-methods-error { 16 | display: flex; 17 | gap: 4px; 18 | align-items: center; 19 | width: fit-content; 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/chevron-up-selected.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/left-arrow-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/people-opened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/right_arrow_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/provider-gitlab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/NoRolesFound.tsx: -------------------------------------------------------------------------------- 1 | import "./noRolesFound.scss"; 2 | 3 | import { ReactComponent as SecuityKeyIcon } from "../../../../assets/roles-and-permissions.svg"; 4 | 5 | export default function NoRolesFound() { 6 | return ( 7 |
8 |
9 | 10 |

Currently, you don’t have any Roles

11 |

Once added, all created user roles will be found here

12 |
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/close-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dashboard 2 | 3 | This is the code for the frontend part of the user management dashboard for user of SuperTokens. This dashboard will eventually allow you to do several actions related to your app users. For example, it will allow you to: 4 | 5 | - See a list of users 6 | - Edit user info 7 | - Delete users 8 | - Manage roles and access control 9 | 10 | This is packaged along with the backend SDK and can be accessed by integrating the backend SDK into your app and visiting: `{apiDomain}/{apiBasePath}/dashboard` 11 | -------------------------------------------------------------------------------- /src/assets/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/star_sparkle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-title.yml: -------------------------------------------------------------------------------- 1 | name: "Lint PR Title" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | jobs: 12 | pr-title: 13 | name: Lint PR title 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: amannn/action-semantic-pull-request@v3 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | with: 20 | validateSingleCommit: true 21 | -------------------------------------------------------------------------------- /src/assets/loader.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/github-actions-changelog.yml: -------------------------------------------------------------------------------- 1 | name: "Enforcing changelog in PRs Workflow" 2 | on: 3 | pull_request: 4 | types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] 5 | 6 | jobs: 7 | # Enforces the update of a changelog file on every pull request 8 | changelog: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: dangoslen/changelog-enforcer@v2 13 | with: 14 | changeLogPath: "CHANGELOG.md" 15 | skipLabels: "Skip-Changelog" 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/assets/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/trash-opened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /config/jest/babelTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const babelJest = require('babel-jest').default; 4 | 5 | const hasJsxRuntime = (() => { 6 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { 7 | return false; 8 | } 9 | 10 | try { 11 | require.resolve('react/jsx-runtime'); 12 | return true; 13 | } catch (e) { 14 | return false; 15 | } 16 | })(); 17 | 18 | module.exports = babelJest.createTransformer({ 19 | presets: [ 20 | [ 21 | require.resolve('babel-preset-react-app'), 22 | { 23 | runtime: hasJsxRuntime ? 'automatic' : 'classic', 24 | }, 25 | ], 26 | ], 27 | babelrc: false, 28 | configFile: false, 29 | }); 30 | -------------------------------------------------------------------------------- /src/ui/components/layout/layoutPanel.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from "react"; 2 | 3 | export type LayoutPanelProps = { 4 | children?: React.ReactNode; 5 | header?: React.ReactNode; 6 | className?: string; 7 | headerBorder?: boolean; 8 | }; 9 | 10 | export const LayoutPanel: FC = ({ children, header, className, headerBorder }) => { 11 | return ( 12 |
13 | {header !== undefined && ( 14 |
15 | {header} 16 |
17 | )} 18 | {children !== undefined &&
{children}
} 19 |
20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/api/search/searchTags.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../utils"; 2 | 3 | type resp = { 4 | status: string; 5 | tags: string[]; 6 | }; 7 | 8 | interface IUseFetchSearchTagsService { 9 | fetchSearchTags: () => Promise; 10 | } 11 | 12 | export const useFetchSearchTags = (): IUseFetchSearchTagsService => { 13 | const fetchData = useFetchData(); 14 | const fetchSearchTags = async () => { 15 | const response = await fetchData({ 16 | url: getApiUrl("/api/search/tags"), 17 | method: "GET", 18 | }); 19 | return response.ok ? ((await response?.json()) as resp) : undefined; 20 | }; 21 | return { fetchSearchTags }; 22 | }; 23 | 24 | export default useFetchSearchTags; 25 | -------------------------------------------------------------------------------- /src/ui/layouts/mainLayout.tsx: -------------------------------------------------------------------------------- 1 | import { Footer } from "../components/footer/footer"; 2 | import Header from "../components/header"; 3 | import SideBar from "../components/sidebar"; 4 | 5 | import "./mainLayout.scss"; 6 | 7 | type MainLayoutProps = { 8 | children: React.ReactNode; 9 | }; 10 | 11 | export default function MainLayout({ children }: MainLayoutProps) { 12 | return ( 13 | <> 14 |
15 |
16 | 17 |
{children}
18 |
23 |
24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/auth-provider.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/auth/SignInContentWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { getAuthMode } from "../../../utils"; 2 | import SignIn from "./SignInContent"; 3 | import SignInWithApiKeyContent from "./SignInWithApiKeyContent"; 4 | 5 | interface SignInContentWrapperProps { 6 | onSuccess: () => void; 7 | onCreateNewUserClick: () => void; 8 | onForgotPasswordBtnClick: () => void; 9 | } 10 | 11 | const SignInContentWrapper: React.FC = ({ ...props }: SignInContentWrapperProps) => { 12 | const authMode = getAuthMode(); 13 | 14 | if (authMode === "email-password") { 15 | return ; 16 | } 17 | 18 | return ; 19 | }; 20 | 21 | export default SignInContentWrapper; 22 | -------------------------------------------------------------------------------- /src/assets/eye.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/envelope-green.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ui/components/tenants/noTenants/noTenants.scss: -------------------------------------------------------------------------------- 1 | .not-found-container { 2 | display: block; 3 | overflow-x: auto; 4 | 5 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.16); 6 | border-radius: 6px; 7 | background-color: var(--color-white); 8 | display: block; 9 | width: 100%; 10 | padding: 56px 0px; 11 | 12 | & > div { 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | 17 | h2 { 18 | color: var(--color-black); 19 | text-align: center; 20 | font-size: 18px; 21 | font-style: normal; 22 | font-weight: 500; 23 | line-height: 40px; 24 | } 25 | 26 | p { 27 | color: var(--color-secondary-text); 28 | text-align: center; 29 | font-size: 14px; 30 | font-style: normal; 31 | font-weight: 400; 32 | line-height: 26px; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/version.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | export const package_version = "0.13.0"; 17 | -------------------------------------------------------------------------------- /src/api/user/email/verify/token.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../../../utils"; 2 | 3 | interface IUseVerifyUserTokenService { 4 | sendUserEmailVerification: (userId: string, tenantId?: string) => Promise; 5 | } 6 | 7 | const useVerifyUserTokenService = (): IUseVerifyUserTokenService => { 8 | const fetchData = useFetchData(); 9 | 10 | const sendUserEmailVerification = async (userId: string, tenantId?: string) => { 11 | const response = await fetchData({ 12 | url: getApiUrl("/api/user/email/verify/token", tenantId), 13 | method: "POST", 14 | config: { 15 | body: JSON.stringify({ 16 | recipeUserId: userId, 17 | }), 18 | }, 19 | }); 20 | return response?.ok; 21 | }; 22 | 23 | return { sendUserEmailVerification }; 24 | }; 25 | 26 | export default useVerifyUserTokenService; 27 | -------------------------------------------------------------------------------- /src/assets/provider-twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/ui/components/common/modals/TenantIdModals.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | @import "../../../styles/mixin.scss"; 16 | -------------------------------------------------------------------------------- /src/ui/styles/index.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import "./index.css"; 17 | import "./variables.css"; 18 | import "./uikit.scss"; 19 | -------------------------------------------------------------------------------- /src/ui/components/tenants/creatNewTenant/createNewTenant.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .create-tenant-dialog-container { 17 | padding: 32px 0 24px 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/assets/lock-opened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/mail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | // HTTP requests & responses related 17 | export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"; 18 | export type HttpApiBaseResponse = { status: "OK" | string }; 19 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/noRolesFound.scss: -------------------------------------------------------------------------------- 1 | .paper-container { 2 | display: block; 3 | overflow-x: auto; 4 | 5 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.16); 6 | border-radius: 6px; 7 | background-color: var(--color-white); 8 | display: block; 9 | width: 100%; 10 | max-width: 100%; 11 | padding: 56px 0px; 12 | 13 | .icon { 14 | height: 54px; 15 | width: 54px; 16 | color: var(--color-primary); 17 | } 18 | 19 | & > div { 20 | display: flex; 21 | flex-direction: column; 22 | align-items: center; 23 | 24 | h1 { 25 | color: var(--color-black); 26 | text-align: center; 27 | font-size: 18px; 28 | font-style: normal; 29 | font-weight: 500; 30 | line-height: 40px; 31 | } 32 | 33 | p { 34 | color: var(--color-secondary-text); 35 | text-align: center; 36 | font-size: 14px; 37 | font-style: normal; 38 | font-weight: 400; 39 | line-height: 26px; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/ui/components/collapsible/collapsible.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .collapsible-content { 17 | overflow: hidden; 18 | // Update time in useEffect if updating animation time 19 | transition: height 0.2s; 20 | } 21 | -------------------------------------------------------------------------------- /src/api/user/unlink.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../utils"; 2 | 3 | type TUnlinkUserResponse = Promise<{ status: "OK" } | undefined>; 4 | 5 | interface IUseUnlinkService { 6 | unlinkUser: (userId: string) => TUnlinkUserResponse; 7 | } 8 | 9 | const useUnlinkService = (): IUseUnlinkService => { 10 | const fetchData = useFetchData(); 11 | 12 | const unlinkUser = async (recipeUserId: string): Promise<{ status: "OK" } | undefined> => { 13 | const response = await fetchData({ 14 | url: getApiUrl("/api/user/unlink"), 15 | method: "GET", 16 | query: { 17 | recipeUserId: recipeUserId, 18 | }, 19 | }); 20 | 21 | if (response.ok) { 22 | const body = await response.json(); 23 | 24 | if (body.status !== "OK") { 25 | return undefined; 26 | } 27 | 28 | return body; 29 | } 30 | 31 | return undefined; 32 | }; 33 | 34 | return { 35 | unlinkUser, 36 | }; 37 | }; 38 | 39 | export default useUnlinkService; 40 | -------------------------------------------------------------------------------- /src/assets/provider-github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/deleteCrossButton/deleteCrossButton.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | .delete-cross-button { 16 | height: 22px; 17 | width: 22px; 18 | border: none; 19 | background: transparent; 20 | 21 | &:disabled { 22 | cursor: not-allowed; 23 | opacity: 0.5; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/user.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { Tenant } from "../api/tenants/types"; 17 | 18 | export function getTenantsObjectsForIds(tenantsFromStore: Tenant[], tenantIds: string[]): Tenant[] { 19 | return tenantsFromStore.filter((tenant) => tenantIds.includes(tenant.tenantId)); 20 | } 21 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/dialogs/createNewRole.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .create-role-dialog-container { 17 | display: flex; 18 | flex-direction: column; 19 | 20 | padding: 32px 0 24px 0; 21 | gap: 20px; 22 | 23 | .margin-bottom-10 { 24 | margin-bottom: 10px; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 17 | // allows you to do things like: 18 | // expect(element).toHaveTextContent(/react/i) 19 | // learn more: https://github.com/testing-library/jest-dom 20 | import "@testing-library/jest-dom"; 21 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/thirdPartyPage/thirdPartyPage.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .third-party-section { 17 | padding: 72px 40px 48px; 18 | max-width: 830px; 19 | margin: auto; 20 | 21 | &__cards { 22 | display: flex; 23 | gap: 32px; 24 | flex-direction: column; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/events/accessDenied.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | export const DASHBOARD_ACCESS_DENIED_EVENT = "dashboard-access-denied"; 17 | 18 | export const getAccessDeniedEvent = (message: string) => { 19 | return new CustomEvent(DASHBOARD_ACCESS_DENIED_EVENT, { 20 | detail: { 21 | message, 22 | }, 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import React from "react"; 17 | import { render, screen } from "@testing-library/react"; 18 | import App from "./App"; 19 | 20 | test("renders learn react link", () => { 21 | render(); 22 | const linkElement = screen.getByText(/learn react/i); 23 | expect(linkElement).toBeInTheDocument(); 24 | }); 25 | -------------------------------------------------------------------------------- /src/ui/components/select/index.tsx: -------------------------------------------------------------------------------- 1 | import "./select.scss"; 2 | 3 | type SelectProps = { 4 | options: { value: string; name: string }[]; 5 | selectedOption: string | undefined; 6 | onOptionSelect: (value: string) => void; 7 | }; 8 | export default function Select({ onOptionSelect, options, selectedOption }: SelectProps) { 9 | function handleChange(e: React.ChangeEvent) { 10 | const selectedOption = options.find((option) => option.value === e.currentTarget.value)!; 11 | onOptionSelect(selectedOption.value); 12 | } 13 | return ( 14 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/api/index.ts: -------------------------------------------------------------------------------- 1 | import { StorageKeys } from "../constants"; 2 | import { localStorageHandler } from "../services/storage"; 3 | import { getApiUrl, useFetchData } from "../utils"; 4 | 5 | const useAuthService = () => { 6 | const fetchData = useFetchData(); 7 | 8 | const logout = async () => { 9 | const response = await fetchData({ 10 | url: getApiUrl("/api/signout"), 11 | method: "POST", 12 | }); 13 | const body = await response.json(); 14 | if (body.status === "OK") { 15 | localStorageHandler.removeItem(StorageKeys.AUTH_KEY); 16 | localStorageHandler.removeItem(StorageKeys.EMAIL); 17 | window.location.reload(); 18 | } 19 | }; 20 | 21 | const signIn = async ({ email, password }: { email: string; password: string }) => { 22 | return await fetchData({ 23 | url: getApiUrl("/api/signin"), 24 | method: "POST", 25 | config: { 26 | body: JSON.stringify({ 27 | email, 28 | password, 29 | }), 30 | }, 31 | }); 32 | }; 33 | 34 | return { 35 | logout, 36 | signIn, 37 | }; 38 | }; 39 | 40 | export default useAuthService; 41 | -------------------------------------------------------------------------------- /src/assets/eye-stroke.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/people-restricted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit-hook-run.yml: -------------------------------------------------------------------------------- 1 | name: "Pre commit hook check" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | jobs: 12 | pr-title: 13 | name: Pre commit hook check 14 | runs-on: ubuntu-latest 15 | container: rishabhpoddar/supertokens_website_sdk_testing_node_16 16 | steps: 17 | - uses: actions/checkout@v2 18 | - run: git init && git add --all && git -c user.name='test' -c user.email='test@example.com' commit -m 'init for pr action' 19 | - run: npm i --force || true 20 | # the below command is there cause otherwise running npm run check-circular-dependencies gives an error like: 21 | # Your cache folder contains root-owned files, due to a bug in 22 | # npm ERR! previous versions of npm which has since been addressed. 23 | - run: chown -R 1001:121 "/github/home/.npm" 24 | - run: npm i --force 25 | - run: ./hooks/pre-commit 26 | -------------------------------------------------------------------------------- /src/assets/form-field-error-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ! 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/mail-opened.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/api/user/delete.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../utils"; 2 | 3 | type TDeleteUserResponse = Promise<{ status: "OK" } | undefined>; 4 | 5 | interface IUseDeleteUserService { 6 | deleteUser: (userId: string, removeAllLinkedAccounts: boolean) => TDeleteUserResponse; 7 | } 8 | 9 | const useDeleteUserService = (): IUseDeleteUserService => { 10 | const fetchData = useFetchData(); 11 | 12 | const deleteUser = async ( 13 | userId: string, 14 | removeAllLinkedAccounts: boolean 15 | ): Promise<{ status: "OK" } | undefined> => { 16 | const response = await fetchData({ 17 | url: getApiUrl("/api/user"), 18 | method: "DELETE", 19 | query: { 20 | userId, 21 | removeAllLinkedAccounts: String(removeAllLinkedAccounts), 22 | }, 23 | }); 24 | 25 | if (response.ok) { 26 | const body = await response.json(); 27 | 28 | if (body.status !== "OK") { 29 | return undefined; 30 | } 31 | 32 | return body; 33 | } 34 | 35 | return undefined; 36 | }; 37 | 38 | return { 39 | deleteUser, 40 | }; 41 | }; 42 | 43 | export default useDeleteUserService; 44 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/deleteThirdPartyClient/deleteThirdPartyClient.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .confirm-text { 17 | color: black; 18 | font-size: 14px; 19 | font-style: normal; 20 | font-weight: 400; 21 | line-height: 23px; 22 | padding-top: 24px; 23 | 24 | .tenant-id { 25 | color: var(--color-button-error); 26 | font-weight: 600; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/deleteTenant/deleteTenant.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .confirm-text { 17 | color: black; 18 | font-size: 14px; 19 | font-style: normal; 20 | font-weight: 400; 21 | line-height: 23px; 22 | padding-top: 24px; 23 | 24 | .client-type { 25 | color: var(--color-button-error); 26 | font-weight: 600; 27 | } 28 | margin-bottom: 12px; 29 | } 30 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/deleteThirdPartyProvider/deleteThirdPartyProvider.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .confirm-text { 17 | color: black; 18 | font-size: 14px; 19 | font-style: normal; 20 | font-weight: 400; 21 | line-height: 23px; 22 | padding-top: 24px; 23 | 24 | .third-party-id { 25 | color: var(--color-button-error); 26 | font-weight: 600; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/loginMethods/components/editableInput.tsx: -------------------------------------------------------------------------------- 1 | import InputField from "../../../inputField/InputField"; 2 | import { PhoneNumberInput } from "../../../phoneNumber/PhoneNumberInput"; 3 | import "./editableInput.scss"; 4 | 5 | export type EditableInputProps = { 6 | label: string; 7 | val: string; 8 | edit: boolean; 9 | type: "email" | "phone"; 10 | onChange: (val: string) => void; 11 | error?: string; 12 | }; 13 | 14 | export const EditableInput = ({ label, val, edit, type, onChange, error }: EditableInputProps) => { 15 | return ( 16 | 17 | {label}: {" "} 18 | {type === "email" && ( 19 | { 26 | onChange(target.value); 27 | }} 28 | /> 29 | )} 30 | {type === "phone" && ( 31 | 37 | )} 38 | 39 | ); 40 | }; 41 | -------------------------------------------------------------------------------- /.vscode/copyright.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "copy-ts-css": { 3 | "scope": "javascript,typescript,typescriptreact,css,scss", 4 | "prefix": ["copyright"], 5 | "description": "Add copyright to typescript, javascript, or css file format", 6 | "body": [ 7 | "/* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.\r", 8 | " *\r", 9 | " * This software is licensed under the Apache License, Version 2.0 (the\r", 10 | " * \"License\") as published by the Apache Software Foundation.\r", 11 | " *\r", 12 | " * You may not use this file except in compliance with the License. You may\r", 13 | " * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\r", 14 | " *\r", 15 | " * Unless required by applicable law or agreed to in writing, software\r", 16 | " * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\r", 17 | " * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r", 18 | " * License for the specific language governing permissions and limitations\r", 19 | " * under the License.\r", 20 | " */" 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ui/components/checkbox/checkbox.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .checkbox-container { 17 | display: flex; 18 | gap: 6px; 19 | align-items: center; 20 | 21 | label { 22 | font-family: inherit; 23 | font-size: 12px; 24 | font-weight: 500; 25 | line-height: 14px; 26 | color: var(--color-secondary); 27 | } 28 | 29 | &--disabled { 30 | opacity: 0.6; 31 | cursor: not-allowed; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ui/components/auth/SignOutBtn.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import useAuthService from "../../../api"; 17 | import Button from "../button"; 18 | import "./SignOutBtn.scss"; 19 | const SignOutBtn = () => { 20 | const { logout } = useAuthService(); 21 | return ( 22 | 27 | ); 28 | }; 29 | 30 | export default SignOutBtn; 31 | -------------------------------------------------------------------------------- /src/ui/styles/mixin.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | @mixin gap-horizontal($gap) { 17 | > :not(:last-child) { 18 | margin-right: $gap; 19 | } 20 | } 21 | 22 | @mixin gap-vertical($gap) { 23 | > :not(:last-child) { 24 | margin-bottom: $gap; 25 | } 26 | } 27 | 28 | @mixin text-ellipsis($max-width) { 29 | max-width: $max-width; 30 | overflow-x: hidden; 31 | text-overflow: ellipsis; 32 | white-space: nowrap; 33 | } 34 | -------------------------------------------------------------------------------- /src/ui/components/pagination/pagination.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | @import "../../styles/mixin.scss"; 17 | 18 | .pagination { 19 | display: flex; 20 | @include gap-horizontal(1em); 21 | 22 | .pagination-count { 23 | font-weight: 500; 24 | } 25 | .pagination-navigation { 26 | display: flex; 27 | @include gap-horizontal(0.5em); 28 | } 29 | .pagination-button { 30 | border: none; 31 | background: none; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/dialogs/editRole.scss: -------------------------------------------------------------------------------- 1 | .edit-role-content { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 24px; 5 | 6 | padding: 32px 0 24px 0; 7 | 8 | & > div { 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | 13 | .permissions-list-container { 14 | display: flex; 15 | flex-wrap: wrap; 16 | 17 | gap: 14px 18px; 18 | overflow: scroll; 19 | max-height: 14vh; 20 | } 21 | 22 | .label { 23 | color: var(--color-secondary-text); 24 | font-size: 14px; 25 | font-style: normal; 26 | font-weight: 500; 27 | line-height: normal; 28 | 29 | margin-bottom: 10px; 30 | } 31 | 32 | .role-name { 33 | color: var(--color-black); 34 | font-size: 14px; 35 | font-style: normal; 36 | font-weight: 600; 37 | line-height: normal; 38 | } 39 | 40 | .delete-badge { 41 | &:hover { 42 | border-radius: 6px; 43 | border: 1px solid var(--light-tags-tag-red-border, #fecdd3); 44 | background: var(--light-tags-tag-red-bg-hover, #fecdd3); 45 | color: rgba(225, 29, 72, 1); 46 | 47 | & > svg { 48 | stroke: rgba(225, 29, 72, 1); 49 | cursor: pointer; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/api/user/password/reset/index.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../../../utils"; 2 | 3 | interface IUsePasswordResetService { 4 | updatePassword: ( 5 | userId: string, 6 | newPassword: string, 7 | tenantId: string | undefined 8 | ) => Promise; 9 | } 10 | 11 | type UpdatePasswordResponse = 12 | | { 13 | status: "OK"; 14 | } 15 | | { 16 | status: "INVALID_PASSWORD_ERROR"; 17 | error: string; 18 | }; 19 | 20 | const usePasswordResetService = (): IUsePasswordResetService => { 21 | const fetchData = useFetchData(); 22 | 23 | const updatePassword = async ( 24 | userId: string, 25 | newPassword: string, 26 | tenantId: string | undefined 27 | ): Promise => { 28 | const response = await fetchData({ 29 | url: getApiUrl("/api/user/password", tenantId), 30 | method: "PUT", 31 | query: { userId }, 32 | config: { 33 | body: JSON.stringify({ 34 | recipeUserId: userId, 35 | newPassword, 36 | }), 37 | }, 38 | }); 39 | return await response.json(); 40 | }; 41 | 42 | return { updatePassword }; 43 | }; 44 | 45 | export default usePasswordResetService; 46 | -------------------------------------------------------------------------------- /src/ui/components/tenants/noTenants/NoTenants.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { ReactComponent as NoTenantsFound } from "../../../../assets/no-tenants.svg"; 16 | import "./noTenants.scss"; 17 | 18 | export const NoTenants = () => { 19 | return ( 20 |
21 |
22 | 23 |

No tenants found

24 |

Can’t find the tenant you are looking for!

25 |
26 |
27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /src/services/storage.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | export const localStorageHandler = { 16 | getItem: (key: string): string | undefined => { 17 | const itemFromStorage = window.localStorage.getItem(key); 18 | 19 | return itemFromStorage === null ? undefined : itemFromStorage; 20 | }, 21 | removeItem: (key: string): void => { 22 | window.localStorage.removeItem(key); 23 | }, 24 | setItem: (key: string, value: string) => { 25 | window.localStorage.setItem(key, value); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/ui/components/loader/Loader.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import "./loader.scss"; 17 | 18 | export const Loader = () => { 19 | return ( 20 |
21 |
22 |
23 | ); 24 | }; 25 | 26 | export const LoaderOverlay = () => { 27 | return ( 28 |
29 |
30 |
31 |
32 |
33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /src/ui/contexts/AppEnvContext.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface IAppEnvContext { 4 | connectionURI: string; 5 | isDemoConnectionURI: boolean; 6 | } 7 | 8 | interface IAppEnvContextProviderProps { 9 | connectionURI: string; 10 | children?: React.ReactNode; 11 | } 12 | 13 | // The list of possible connection URIs 14 | const DEMO_CONNECTION_URIS = ["try.supertokens.io", "try.supertokens.com"]; 15 | 16 | const AppEnvContext = React.createContext(null); 17 | 18 | export const useAppEnvContext = () => { 19 | const context = React.useContext(AppEnvContext); 20 | if (!context) throw "Context must be used within a provider!"; 21 | return context; 22 | }; 23 | 24 | export const AppEnvContextProvider: React.FC = ({ connectionURI, children }) => { 25 | const isDemoConnectionUri = (connectionURI: string) => { 26 | return DEMO_CONNECTION_URIS.some((domains) => connectionURI.includes(domains)); 27 | }; 28 | 29 | const contextValue: IAppEnvContext = { 30 | connectionURI, 31 | isDemoConnectionURI: isDemoConnectionUri(connectionURI), 32 | }; 33 | 34 | return {children}; 35 | }; 36 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/userRoles/UserRolesListHeader.tsx: -------------------------------------------------------------------------------- 1 | import { getImageUrl } from "../../../../utils"; 2 | import Button from "../../button"; 3 | import IconButton from "../../common/iconButton"; 4 | 5 | type UserRolesListHeaderProps = { 6 | setIsEditing: (value: boolean) => void; 7 | isEditing: boolean; 8 | isFeatureEnabled: boolean | undefined; 9 | }; 10 | 11 | export const UserRolesListHeader = ({ setIsEditing, isEditing, isFeatureEnabled }: UserRolesListHeaderProps) => { 12 | return ( 13 | <> 14 |
15 |
Assigned User Roles
16 |
17 | {isFeatureEnabled ? ( 18 | <> 19 | {!isEditing ? ( 20 | { 26 | setIsEditing(true); 27 | }} 28 | /> 29 | ) : ( 30 |
31 | 37 |
38 | )} 39 | 40 | ) : null} 41 | 42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /src/ui/components/alert/index.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import "./alert.scss"; 17 | 18 | type AlertProps = { 19 | type?: "primary" | "secondary"; 20 | padding?: "sm" | "md"; 21 | title: string; 22 | children: React.ReactNode; 23 | }; 24 | 25 | export default function Alert({ children, title, type = "primary", padding = "md" }: AlertProps) { 26 | return ( 27 |
28 | {title} 29 |
{children}
30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/ui/components/errorBlock/ErrorBlock.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { ReactNode } from "react"; 16 | import { ReactComponent as ErrorIcon } from "../../../assets/form-field-error-icon.svg"; 17 | import "./errorBlock.scss"; 18 | 19 | export const ErrorBlock = ({ children, className }: { children: ReactNode; className?: string }) => { 20 | return ( 21 |
22 | 23 |

{children}

24 |
25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /src/assets/no-users-graphic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /server/go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/supertokens/dashboard 2 | 3 | go 1.17 4 | 5 | require github.com/supertokens/supertokens-golang v0.10.3-0.20230327084802-52a32af8ea1b 6 | 7 | require ( 8 | github.com/MicahParks/keyfunc v1.0.0 // indirect 9 | github.com/davecgh/go-spew v1.1.1 // indirect 10 | github.com/derekstavis/go-qs v0.0.0-20180720192143-9eef69e6c4e7 // indirect 11 | github.com/golang-jwt/jwt/v4 v4.1.0 // indirect 12 | github.com/golang/mock v1.6.0 // indirect 13 | github.com/golang/protobuf v1.3.2 // indirect 14 | github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect 15 | github.com/nyaruka/phonenumbers v1.0.73 // indirect 16 | github.com/pkg/errors v0.9.1 // indirect 17 | github.com/pmezard/go-difflib v1.0.0 // indirect 18 | github.com/stretchr/testify v1.7.0 // indirect 19 | github.com/twilio/twilio-go v0.26.0 // indirect 20 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect 21 | golang.org/x/text v0.3.7 // indirect 22 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect 23 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect 24 | gopkg.in/h2non/gock.v1 v1.1.2 // indirect 25 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { ReportHandler } from "web-vitals"; 17 | 18 | const reportWebVitals = async (onPerfEntry?: ReportHandler) => { 19 | if (onPerfEntry && onPerfEntry instanceof Function) { 20 | await import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 21 | getCLS(onPerfEntry); 22 | getFID(onPerfEntry); 23 | getFCP(onPerfEntry); 24 | getLCP(onPerfEntry); 25 | getTTFB(onPerfEntry); 26 | }); 27 | } 28 | }; 29 | 30 | export default reportWebVitals; 31 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/tenantList/UserTenantsList.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | @import "../../../styles/mixin.scss"; 16 | 17 | .tenant-pill { 18 | padding: 5px 13px; 19 | border-radius: 30px; 20 | border: 1px solid #9335e4; 21 | background: rgba(147, 53, 228, 0.1); 22 | max-width: fit-content; 23 | color: #9335e4; 24 | font-size: 14px; 25 | margin-left: 10px; 26 | } 27 | 28 | .tenant-list-container { 29 | display: flex; 30 | flex-direction: row; 31 | flex-wrap: wrap; 32 | row-gap: 16px; 33 | column-gap: 16px; 34 | } 35 | -------------------------------------------------------------------------------- /src/ui/components/common/iconButton/index.tsx: -------------------------------------------------------------------------------- 1 | import "./style.scss"; 2 | 3 | export type IconButtonProps = { 4 | size: "small" | "medium" | "large"; 5 | icon: string; 6 | text: string; 7 | tint: string; 8 | onClick: () => void | Promise; 9 | }; 10 | 11 | const IconButton: React.FC = ({ size, icon, text, tint, onClick }: IconButtonProps) => { 12 | const getClassNameForFont = (): string => { 13 | if (size === "small") { 14 | return "text-small"; 15 | } 16 | 17 | if (size === "medium") { 18 | return "text-medium"; 19 | } 20 | 21 | return "text-large"; 22 | }; 23 | 24 | const getImageDimension = (): number => { 25 | if (size === "small") { 26 | return 12; 27 | } 28 | 29 | if (size === "medium") { 30 | return 14; 31 | } 32 | 33 | return 16; 34 | }; 35 | 36 | const imageDimension = getImageDimension(); 37 | 38 | return ( 39 |
42 | 47 | 52 | {text} 53 | 54 |
55 | ); 56 | }; 57 | 58 | export default IconButton; 59 | -------------------------------------------------------------------------------- /src/assets/phone-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/errorboundary/error-boundary.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .error-container { 17 | width: 100%; 18 | height: 100%; 19 | display: flex; 20 | justify-content: center; 21 | align-items: center; 22 | .block-container { 23 | text-align: center; 24 | max-width: 560px; 25 | margin: 32px auto; 26 | .text-title { 27 | font-size: 24px; 28 | line-height: normal; 29 | margin-top: 8px; 30 | } 31 | .title-image { 32 | margin-left: auto; 33 | margin-right: auto; 34 | } 35 | p { 36 | margin-top: 12px; 37 | letter-spacing: 0.14px; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/ui/components/badge/index.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import "./badge.scss"; 17 | 18 | export type BadgeProps = { 19 | children?: React.ReactNode; 20 | className?: string; 21 | text: string; 22 | type?: "secondary" | "success"; 23 | size?: "xs" | "sm" | "md" | "lg"; 24 | }; 25 | 26 | export default function Badge(props: BadgeProps) { 27 | const { children, type = "secondary", className = "", size = "md", text } = props; 28 | return ( 29 | 30 | {text} 31 | {children} 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/assets/provider-google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/uneditablePropertyDialog/UneditablePropertyDialog.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { Dialog, DialogConfirmText, DialogContent } from "../../../dialog"; 16 | 17 | export const UneditablePropertyDialog = ({ 18 | onCloseDialog, 19 | children, 20 | }: { 21 | onCloseDialog: () => void; 22 | children: React.ReactNode; 23 | }) => { 24 | return ( 25 | 28 | 29 | {children} 30 | 31 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.packageManager": "npm", 3 | "eslint.options": { 4 | "extensions": [".ts", ".tsx", ".html"] 5 | }, 6 | "eslint.lintTask.options": "--ext .ts, .tsx", 7 | "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "html"], 8 | "editor.rulers": [120], 9 | "html.format.wrapLineLength": 120, 10 | "html.format.extraLiners": "", 11 | "html.format.indentInnerHtml": true, 12 | "editor.tabCompletion": "on", 13 | "editor.tabSize": 4, 14 | "editor.useTabStops": true, 15 | "editor.trimAutoWhitespace": true, 16 | "editor.formatOnSave": true, 17 | "editor.codeActionsOnSave": { 18 | "source.organizeImports": "explicit" 19 | }, 20 | "files.exclude": { 21 | "**/.DS_Store": true, 22 | "**/.git": true, 23 | "dist": true, 24 | "debug": true, 25 | "cypress/integration/examples": true 26 | }, 27 | "files.insertFinalNewline": true, 28 | "files.trimTrailingWhitespace": true, 29 | "typescript.tsdk": "./node_modules/typescript/lib", 30 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 31 | "typescript.preferences.quoteStyle": "double", 32 | "json.format.enable": true, 33 | "json.format.keepLines": true, 34 | "html.format.enable": false, 35 | "typescript.format.semicolons": "insert", 36 | "python.analysis.typeCheckingMode": "off" 37 | } 38 | -------------------------------------------------------------------------------- /src/ui/components/recipePill/RecipePill.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | type RecipePillProps = { 17 | recipeId: "emailpassword" | "thirdparty" | "passwordless" | "multiple"; 18 | label: string; 19 | thirdpartyId?: string; 20 | }; 21 | 22 | export const RecipePill = ({ recipeId, label, thirdpartyId }: RecipePillProps) => { 23 | return ( 24 |
25 | {label} 26 | {thirdpartyId && ( 27 | 30 | {" "} 31 | - {thirdpartyId} 32 | 33 | )} 34 |
35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import React from "react"; 17 | import ReactDOM from "react-dom/client"; 18 | import App from "./App"; 19 | import reportWebVitals from "./reportWebVitals"; 20 | import "./ui/styles"; 21 | 22 | const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); 23 | root.render( 24 | 25 | 26 | 27 | ); 28 | 29 | // If you want to start measuring performance in your app, pass a function 30 | // to log results (for example: reportWebVitals(console.log)) 31 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 32 | void reportWebVitals(); 33 | -------------------------------------------------------------------------------- /src/ui/components/inputField/tagsInputField.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .tags-input-field-container { 17 | width: 100%; 18 | height: fit-content; 19 | 20 | p { 21 | color: var(--color-gray); 22 | font-family: Rubik; 23 | font-size: 14px; 24 | font-style: normal; 25 | font-weight: 400; 26 | line-height: normal; 27 | 28 | margin-top: 8px; 29 | } 30 | } 31 | 32 | .tags-container { 33 | display: flex; 34 | justify-content: flex-start; 35 | flex-wrap: wrap; 36 | gap: 10px 16px; 37 | 38 | max-height: 16vh; 39 | overflow: scroll; 40 | 41 | margin-top: 10px; 42 | 43 | svg { 44 | stroke: #2563eb; 45 | cursor: pointer; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ui/components/searchInput/SearchInput.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { getImageUrl } from "../../../utils"; 3 | import "./searchInput.scss"; 4 | 5 | const searchIcon = getImageUrl("search.png"); 6 | const clearIcon = getImageUrl("clear.svg"); 7 | 8 | type SearchInputProps = React.InputHTMLAttributes & { 9 | onClear: () => void; 10 | value: string; 11 | }; 12 | 13 | export const SearchInput = ({ onClear, ...rest }: SearchInputProps) => { 14 | const [active, setActive] = useState(false); 15 | 16 | return ( 17 |
18 | 22 | { 26 | setActive(true); 27 | // eslint-disable-next-line react/prop-types 28 | rest?.onFocus?.(e); 29 | }} 30 | onBlur={(e) => { 31 | setActive(false); 32 | // eslint-disable-next-line react/prop-types 33 | rest?.onBlur?.(e); 34 | }} 35 | /> 36 | {(active || rest?.value) && ( 37 | 48 | )} 49 |
50 | ); 51 | }; 52 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/loginMethods/components/dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdown { 2 | position: relative; 3 | cursor: pointer; 4 | 5 | .trigger { 6 | border-radius: 4px; 7 | border: 1px solid #ddd; 8 | background: #f5f5f5; 9 | padding: 8px; 10 | 11 | &:hover { 12 | background: #fff; 13 | border: 1px solid #f93; 14 | } 15 | 16 | &.open { 17 | background: #fff; 18 | border: 1px solid #f93; 19 | outline: 1px solid rgba(255, 153, 51, 0.4); 20 | } 21 | } 22 | 23 | .menu { 24 | display: none; 25 | position: absolute; 26 | 27 | border-radius: 6px; 28 | background: #fff; 29 | box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.16); 30 | 31 | padding: 6px; 32 | 33 | top: 30px; 34 | right: 10%; 35 | 36 | z-index: 10; 37 | 38 | div { 39 | width: 160px; 40 | padding: 6px 8px; 41 | 42 | display: flex; 43 | align-items: baseline; 44 | justify-content: flex-start; 45 | 46 | img { 47 | height: 14px; 48 | width: 18px; 49 | margin-right: 10px; 50 | } 51 | 52 | &:last-child { 53 | align-items: center; 54 | img { 55 | height: 20px; 56 | } 57 | } 58 | 59 | &:hover { 60 | border-radius: 4px; 61 | background: #f0f0f0; 62 | &:last-child { 63 | color: #9e2526; 64 | background: rgba(222, 35, 61, 0.12); 65 | } 66 | } 67 | } 68 | } 69 | 70 | .menu.open { 71 | display: block; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/ui/components/errorBlock/errorBlock.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .error-block { 17 | border: 1px solid var(--color-border-error-block); 18 | background-color: var(--color-error-block-bg); 19 | border-radius: 6px; 20 | padding: 14px 18px; 21 | display: flex; 22 | gap: 10px; 23 | 24 | a { 25 | font-weight: 500; 26 | color: var(--color-border-error-block); 27 | background-color: transparent !important; 28 | } 29 | 30 | & > svg { 31 | min-width: 19px; 32 | height: 17px; 33 | transform: translateY(2px); 34 | } 35 | 36 | &__error-message { 37 | font-family: inherit; 38 | font-size: 14px; 39 | line-height: 23px; 40 | color: var(--color-black); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/ui/components/footer/footer.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .footer { 17 | bottom: 0; 18 | min-height: 62px; 19 | display: flex; 20 | padding: 20px 32px; 21 | z-index: 20; 22 | 23 | .logo { 24 | height: 23px; 25 | width: 151px; 26 | } 27 | 28 | &.alignment-right { 29 | justify-content: flex-end; 30 | } 31 | &.alignment-center { 32 | justify-content: center; 33 | } 34 | 35 | &.vertical-center { 36 | align-items: center; 37 | } 38 | &.vertical-bottom { 39 | align-self: flex-end; 40 | } 41 | 42 | &.color-dark { 43 | background-color: var(--color-black); 44 | .logo { 45 | width: 148px; 46 | } 47 | } 48 | 49 | &.size-large { 50 | padding: 40px 32px; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ui/components/sidebar/sidebar.scss: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | position: fixed; 3 | height: 100vh; 4 | width: var(--sidebar-width); 5 | margin-top: 64px; 6 | border-right: 1px solid var(--light-borders-border-base, #e5e7eb); 7 | background-color: var(--color-window-bg); 8 | z-index: 10; 9 | } 10 | 11 | .sidebar-list { 12 | margin-top: 50px; 13 | list-style-type: none; 14 | } 15 | 16 | .sidebar-list > li { 17 | margin: 14px 16px; 18 | 19 | & .active { 20 | border-radius: 6px; 21 | border: 1px solid rgba(255, 153, 51, 0.15); 22 | background: rgba(255, 153, 51, 0.1); 23 | 24 | color: #f93; 25 | font-weight: 500; 26 | 27 | & > svg { 28 | stroke: var(--color-primary); 29 | stroke-width: 0.3px; 30 | } 31 | 32 | &:hover { 33 | background: rgba(255, 153, 51, 0.1) !important; 34 | } 35 | } 36 | } 37 | 38 | .sidebar-list > li > a { 39 | display: block; 40 | padding: 6px 8px; 41 | border-radius: 6px; 42 | 43 | color: var(--light-foregrounds-fg-subtle, #4b5563); 44 | font-size: 13px; 45 | font-style: normal; 46 | font-weight: 400; 47 | line-height: 20px; 48 | 49 | border: 1px solid transparent; 50 | 51 | text-decoration: none; 52 | 53 | display: flex; 54 | justify-content: flex-start; 55 | gap: 12px; 56 | 57 | &:hover:not(.active) { 58 | background: #eee !important; 59 | } 60 | } 61 | 62 | @media (max-width: 1024px) { 63 | .sidebar { 64 | display: none; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/ui/components/common/modals/TenantIdModals.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { LayoutModalProps } from "../../layout/layoutModal"; 17 | 18 | export type MissingTenantIdModalProps = Omit & { 19 | message: string; 20 | }; 21 | 22 | export const getMissingTenantIdModalProps = (props: MissingTenantIdModalProps): LayoutModalProps => { 23 | const closeModalRef: React.MutableRefObject<(() => void) | undefined> = { current: undefined }; 24 | 25 | return { 26 | ...props, 27 | modalContent:
{props.message}
, 28 | header:

Operation not allowed

, 29 | closeCallbackRef: closeModalRef, 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /src/utils/form.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-useless-escape */ 2 | 3 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 4 | * 5 | * This software is licensed under the Apache License, Version 2.0 (the 6 | * "License") as published by the Apache Software Foundation. 7 | * 8 | * You may not use this file except in compliance with the License. You may 9 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | import { isValidPhoneNumber } from "libphonenumber-js"; 19 | 20 | export const validateEmail = (email: string) => { 21 | // We use the same regex as supertokens-root 22 | const regexPatternForEmail = 23 | "((^<>()[].,;:@]+(.^<>()[].,;:@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$"; 24 | return new RegExp(regexPatternForEmail).test(email); 25 | }; 26 | 27 | export const isNotEmpty = (value: any) => { 28 | return !(value === undefined || value === null || `${value}`.trim().length === 0); 29 | }; 30 | 31 | export const validatePhoneNumber = isValidPhoneNumber; 32 | -------------------------------------------------------------------------------- /src/assets/provider-linkedin.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /src/api/user/sessions.ts: -------------------------------------------------------------------------------- 1 | import { SessionInfo } from "../../ui/components/userDetail/userDetailSessionList"; 2 | import { getApiUrl, useFetchData } from "../../utils"; 3 | 4 | interface IUseSessionsForUserService { 5 | getSessionsForUser: (userId: string) => Promise; 6 | deleteSessionsForUser: (sessionHandles: string[]) => Promise; 7 | } 8 | 9 | const useSessionsForUserService = (): IUseSessionsForUserService => { 10 | const fetchData = useFetchData(); 11 | 12 | const getSessionsForUser = async (userId: string): Promise => { 13 | const response = await fetchData({ 14 | url: getApiUrl("/api/user/sessions"), 15 | method: "GET", 16 | query: { 17 | userId, 18 | }, 19 | }); 20 | 21 | if (response.ok) { 22 | const body = await response.json(); 23 | 24 | if (body.status !== "OK") { 25 | return undefined; 26 | } 27 | 28 | return body.sessions; 29 | } 30 | 31 | return undefined; 32 | }; 33 | 34 | const deleteSessionsForUser = async (sessionHandles: string[]): Promise => { 35 | await fetchData({ 36 | url: getApiUrl("/api/user/sessions"), 37 | method: "POST", 38 | config: { 39 | body: JSON.stringify({ 40 | sessionHandles, 41 | }), 42 | }, 43 | }); 44 | 45 | return; 46 | }; 47 | 48 | return { 49 | getSessionsForUser, 50 | deleteSessionsForUser, 51 | }; 52 | }; 53 | 54 | export default useSessionsForUserService; 55 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/rolesTable.scss: -------------------------------------------------------------------------------- 1 | .delete-btn-container { 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-between; 5 | } 6 | 7 | .roles-column { 8 | width: 20% !important; 9 | } 10 | 11 | .permissions-container { 12 | display: flex; 13 | justify-content: space-between; 14 | align-items: center; 15 | gap: 14px; 16 | 17 | & > .permissions { 18 | display: flex; 19 | gap: 24px; 20 | overflow: hidden; 21 | 22 | .badge-width { 23 | width: 80px !important; 24 | } 25 | } 26 | 27 | & > .delete-role { 28 | padding: 6px; 29 | border-radius: 3px; 30 | border: 1px solid #ddd; 31 | background: #fff; 32 | 33 | & > svg > path { 34 | fill: rgba(141, 141, 141, 1) !important; 35 | } 36 | 37 | &:hover { 38 | border: 1px solid #ed344e; 39 | background: rgba(237, 52, 78, 0.15); 40 | 41 | & > svg > path { 42 | fill: rgba(237, 52, 78, 1) !important; 43 | } 44 | } 45 | } 46 | 47 | & > .refresh-btn { 48 | padding: 6px; 49 | border-radius: 3px; 50 | 51 | border: 1px solid #ddd; 52 | color: rgba(141, 141, 141, 1); 53 | background: #fff; 54 | 55 | &:hover { 56 | border: 1px solid var(--color-primary); 57 | color: var(--color-primary); 58 | background: rgba(255, 153, 51, 0.06); 59 | } 60 | } 61 | } 62 | 63 | .roles-list-pagination { 64 | justify-content: flex-end; 65 | padding: 24px; 66 | } 67 | 68 | .margin-bottom-36 { 69 | margin-bottom: 36px; 70 | } 71 | -------------------------------------------------------------------------------- /src/ui/components/checkbox/Checkbox.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { ChangeEvent } from "react"; 16 | import "./checkbox.scss"; 17 | 18 | export const Checkbox = ({ 19 | id, 20 | label, 21 | onChange, 22 | checked, 23 | disabled, 24 | }: { 25 | id: string; 26 | label: string; 27 | onChange: (e: ChangeEvent) => void; 28 | checked: boolean; 29 | disabled?: boolean; 30 | }) => { 31 | return ( 32 |
33 | 41 | 42 |
43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /src/assets/edit-unfilled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/createUser/createUserDialog.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .create-user-modal-content { 17 | display: flex; 18 | flex-direction: column; 19 | gap: 16px; 20 | margin-top: 16px; 21 | 22 | .select-container { 23 | display: flex; 24 | flex-direction: column; 25 | align-items: flex-start; 26 | gap: 10px; 27 | } 28 | 29 | .mb-28 { 30 | margin-bottom: 28px; 31 | } 32 | .mb-12 { 33 | margin-bottom: 12px; 34 | } 35 | } 36 | 37 | .dialog-form-content-container { 38 | display: flex; 39 | flex-direction: column; 40 | gap: 20px; 41 | padding: 30px 0px; 42 | } 43 | 44 | .max-width-436 { 45 | max-width: 436px !important; 46 | } 47 | 48 | .pb-0 { 49 | padding-bottom: 0px !important; 50 | } 51 | 52 | .mt-10 { 53 | margin-top: 10px; 54 | } 55 | -------------------------------------------------------------------------------- /src/assets/provider-discord.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/ui/components/toggle/Toggle.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { InputHTMLAttributes } from "react"; 17 | import "./toggle.scss"; 18 | 19 | type ToggleProps = InputHTMLAttributes & { 20 | id: string; 21 | checked: boolean; 22 | label?: string; 23 | }; 24 | 25 | export const Toggle = (props: ToggleProps) => { 26 | const { className, id, label, ...rest } = props; 27 | return ( 28 |
29 | {label && ( 30 | 35 | )} 36 | 42 | 43 |
44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /src/ui/components/noUsers/NoUsers.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .no-users { 17 | padding: 60px 24px; 18 | display: flex; 19 | flex-flow: column; 20 | align-items: center; 21 | } 22 | 23 | .no-users-image { 24 | height: 43px; 25 | width: 63px; 26 | margin-bottom: 24px; 27 | } 28 | 29 | .no-users-title { 30 | font-size: 18px; 31 | line-height: 22px; 32 | font-weight: 500; 33 | color: var(--color-black); 34 | letter-spacing: 0.18px; 35 | margin-bottom: 8px; 36 | text-align: center; 37 | } 38 | 39 | .no-users .no-users-subtitle { 40 | color: var(--color-secondary-text); 41 | padding: 4px 0; 42 | text-align: center; 43 | max-width: 54ch; 44 | line-height: 1.5em; 45 | } 46 | 47 | @media only screen and (min-width: 992px) { 48 | .no-users { 49 | padding: 60px; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ui/components/phoneNumber/PhoneNumber.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { parsePhoneNumber } from "libphonenumber-js/max"; 17 | import { useAppEnvContext } from "../../contexts/AppEnvContext"; 18 | import "./PhoneNumber.scss"; 19 | 20 | export const PhoneDisplay = ({ phone }: { phone: string }) => { 21 | const { isDemoConnectionURI } = useAppEnvContext(); 22 | if (isDemoConnectionURI) return <>{phone}; 23 | let finalPhone = phone; 24 | 25 | try { 26 | const parsed = parsePhoneNumber(phone) || {}; 27 | finalPhone = parsed.formatInternational(); 28 | } catch (_) { 29 | // ignored 30 | } 31 | 32 | return ( 33 | <> 34 |
35 | {finalPhone} 36 |
37 | 38 | ); 39 | }; 40 | 41 | export default PhoneDisplay; 42 | -------------------------------------------------------------------------------- /src/api/users/count.ts: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { UserListCount } from "../../ui/pages/usersList/types"; 17 | import { getApiUrl, useFetchData } from "../../utils"; 18 | 19 | interface IUseFetchCountService { 20 | fetchCount: (tenantid?: string) => Promise; 21 | } 22 | 23 | const useFetchCountService = (): IUseFetchCountService => { 24 | const fetchData = useFetchData(); 25 | 26 | const fetchCount = async (tenantId?: string) => { 27 | const response = await fetchData({ 28 | url: getApiUrl("/api/users/count", tenantId), 29 | method: "GET", 30 | }); 31 | 32 | return response.ok ? ((await response?.json()) as UserListCount) : undefined; 33 | }; 34 | 35 | return { 36 | fetchCount, 37 | }; 38 | }; 39 | 40 | export default useFetchCountService; 41 | -------------------------------------------------------------------------------- /src/assets/clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/api/user/email/verify/index.ts: -------------------------------------------------------------------------------- 1 | import { EmailVerificationStatus } from "../../../../ui/pages/usersList/types"; 2 | import { getApiUrl, useFetchData } from "../../../../utils"; 3 | 4 | interface IUseVerifyUserEmailService { 5 | getUserEmailVerificationStatus: (userId: string) => Promise; 6 | updateUserEmailVerificationStatus: ( 7 | userId: string, 8 | isEmailVerified: boolean, 9 | tenantId: string | undefined 10 | ) => Promise; 11 | } 12 | 13 | const useVerifyUserEmail = (): IUseVerifyUserEmailService => { 14 | const fetchData = useFetchData(); 15 | 16 | const getUserEmailVerificationStatus = async (userId: string): Promise => { 17 | const response = await fetchData({ 18 | url: getApiUrl("/api/user/email/verify"), 19 | method: "GET", 20 | query: { recipeUserId: userId }, 21 | }); 22 | 23 | const body = await response.json(); 24 | return body; 25 | }; 26 | 27 | const updateUserEmailVerificationStatus = async ( 28 | userId: string, 29 | isEmailVerified: boolean, 30 | tenantId: string | undefined 31 | ) => { 32 | const response = await fetchData({ 33 | url: getApiUrl("/api/user/email/verify", tenantId), 34 | method: "PUT", 35 | config: { 36 | body: JSON.stringify({ verified: isEmailVerified, recipeUserId: userId }), 37 | }, 38 | }); 39 | return response?.ok; 40 | }; 41 | 42 | return { 43 | getUserEmailVerificationStatus, 44 | updateUserEmailVerificationStatus, 45 | }; 46 | }; 47 | 48 | export default useVerifyUserEmail; 49 | -------------------------------------------------------------------------------- /src/ui/components/safeAreaView/SafeAreaView.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { HTMLAttributes } from "react"; 17 | import { Helmet } from "react-helmet"; 18 | 19 | type SafeAreaViewProps = { 20 | backgroundColor?: string; 21 | }; 22 | 23 | export const SafeAreaView = (props: SafeAreaViewProps) => { 24 | let backgroundColor = props.backgroundColor; 25 | 26 | if (backgroundColor === undefined) { 27 | backgroundColor = getComputedStyle(document.body).getPropertyValue("--color-window-bg"); 28 | } 29 | const htmlProps = { style: `background-color: ${backgroundColor}` } as HTMLAttributes; 30 | return ( 31 | 32 | 33 | 37 | 38 | ); 39 | }; 40 | 41 | export default SafeAreaView; 42 | -------------------------------------------------------------------------------- /src/assets/close-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/close-inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/tenantList/UserTenantsList.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { LayoutPanel } from "../../layout/layoutPanel"; 16 | import "./UserTenantsList.scss"; 17 | 18 | type Props = { 19 | tenantIds: string[]; 20 | }; 21 | 22 | const Header = () => { 23 | return
Tenant IDs
; 24 | }; 25 | 26 | export const UserTenantsList = (props: Props) => { 27 | return ( 28 | }> 29 |
30 | {props.tenantIds.map((tenantId) => { 31 | return ( 32 |
35 | {tenantId} 36 |
37 | ); 38 | })} 39 | 40 | {props.tenantIds.length === 0 &&
No associated tenants
} 41 |
42 |
43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /src/ui/components/layout/accessDeniedModal.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { useContext } from "react"; 17 | import { AccessDeniedPopupContext } from "../../contexts/AccessDeniedContext"; 18 | import { LayoutModalContent } from "./layoutModal"; 19 | 20 | export const AccessDeniedModal = () => { 21 | const context = useContext(AccessDeniedPopupContext); 22 | 23 | if (context === undefined) { 24 | throw new Error("Access denied modal must be used within the AccessDeninedContext."); 25 | } 26 | 27 | if (context.isPopupVisible === false) { 28 | return <>; 29 | } 30 | 31 | return ( 32 | Access Denied} 35 | onClose={() => { 36 | context.hidePopup(); 37 | }}> 38 |

{context.popupMessage}

39 |
40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | const jest = require('jest'); 19 | const execSync = require('child_process').execSync; 20 | let argv = process.argv.slice(2); 21 | 22 | function isInGitRepository() { 23 | try { 24 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 25 | return true; 26 | } catch (e) { 27 | return false; 28 | } 29 | } 30 | 31 | function isInMercurialRepository() { 32 | try { 33 | execSync('hg --cwd . root', { stdio: 'ignore' }); 34 | return true; 35 | } catch (e) { 36 | return false; 37 | } 38 | } 39 | 40 | // Watch unless on CI or explicitly running all tests 41 | if ( 42 | !process.env.CI && 43 | argv.indexOf('--watchAll') === -1 && 44 | argv.indexOf('--watchAll=false') === -1 45 | ) { 46 | // https://github.com/facebook/create-react-app/issues/5210 47 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 48 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 49 | } 50 | 51 | 52 | jest.run(argv); 53 | -------------------------------------------------------------------------------- /src/assets/green-check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/noUsers/NoUsers.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { getImageUrl } from "../../../utils"; 17 | 18 | import "./NoUsers.css"; 19 | 20 | const NoUsers = (props: { isSearch: boolean }) => { 21 | return ( 22 |
23 | Orange and blue users 28 | 29 |

30 | {!props.isSearch && "Currently, you don't have any users."} 31 | {props.isSearch && " No search results."} 32 |

33 | {!props.isSearch && ( 34 |

35 | If you are using just the session management feature of SuperTokens, your users will not appear in 36 | this list. 37 |

38 | )} 39 |
40 | ); 41 | }; 42 | 43 | export default NoUsers; 44 | -------------------------------------------------------------------------------- /src/assets/tenant-management.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/ui/components/button/index.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { ReactComponent as SpinnerIcon } from "../../../assets/spinner.svg"; 17 | 18 | import "./button.scss"; 19 | 20 | type ButtonProps = { 21 | color?: 22 | | "primary" 23 | | "secondary" 24 | | "info" 25 | | "danger" 26 | | "outline" 27 | | "gray" 28 | | "danger-outline" 29 | | "gray-outline" 30 | | "blue-outline"; 31 | size?: "xs" | "sm" | "md" | "lg"; 32 | isLoading?: boolean; 33 | } & JSX.IntrinsicElements["button"]; 34 | 35 | export default function Button(props: ButtonProps) { 36 | const { color = "primary", size = "md", className = "", isLoading, children, ...rest } = props; 37 | return ( 38 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /src/ui/pages/userroles/index.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .userroles-container { 17 | max-width: var(--container-width); 18 | height: 100%; 19 | padding: 72px 0px 0px; 20 | margin: auto; 21 | 22 | .userroles-title { 23 | font-size: 28px; 24 | line-height: 34px; 25 | color: var(--color-black); 26 | margin-bottom: 16px; 27 | font-weight: 500; 28 | } 29 | 30 | .userroles-subtitle { 31 | color: var(--color-secondary-text); 32 | margin-bottom: 48px; 33 | } 34 | 35 | .search-add-role-container { 36 | display: flex; 37 | justify-content: flex-end; 38 | align-items: center; 39 | margin-bottom: 12px; 40 | } 41 | } 42 | 43 | @media (max-width: 1024px) { 44 | .userroles-container { 45 | padding: 72px 40px 48px; 46 | max-width: 100%; 47 | } 48 | } 49 | 50 | @media (max-width: 480px) { 51 | .userroles-container { 52 | padding: 72px 18px 48px; 53 | max-width: 100%; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/assets/checkmark-green.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /server/python/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask import Flask, abort, g, jsonify 4 | from flask_cors import CORS 5 | from supertokens_python import ( 6 | get_all_cors_headers, 7 | init, 8 | ) 9 | from supertokens_python.framework.flask import Middleware 10 | from supertokens_python.recipe.session.framework.flask import verify_session 11 | import config 12 | 13 | init( 14 | supertokens_config=config.supertokens_config, 15 | app_info=config.app_info, 16 | framework=config.framework, 17 | recipe_list=config.recipe_list, 18 | ) 19 | 20 | app = Flask(__name__) 21 | 22 | Middleware(app) 23 | CORS( 24 | app=app, 25 | supports_credentials=True, 26 | origins="http://localhost:3000", 27 | allow_headers=["Content-Type"] + get_all_cors_headers(), 28 | ) 29 | 30 | 31 | @app.route("/sessioninfo", methods=["GET"]) # type: ignore 32 | @verify_session() 33 | def get_session_info(): 34 | session_ = g.supertokens 35 | return jsonify( 36 | { 37 | "sessionHandle": session_.get_handle(), 38 | "userId": session_.get_user_id(), 39 | "accessTokenPayload": session_.get_access_token_payload(), 40 | } 41 | ) 42 | 43 | 44 | # This is required since if this is not there, then OPTIONS requests for 45 | # the APIs exposed by the supertokens' Middleware will return a 404 46 | @app.route("/", defaults={"u_path": ""}) # type: ignore 47 | @app.route("/") # type: ignore 48 | def catch_all(u_path: str): # pylint: disable=unused-argument 49 | abort(404) 50 | 51 | 52 | if __name__ == "__main__": 53 | app.run(host="0.0.0.0", port=int("3001"), debug=True) 54 | -------------------------------------------------------------------------------- /src/assets/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/assets/user-managment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/searchInput/searchInput.scss: -------------------------------------------------------------------------------- 1 | .search { 2 | & > div { 3 | display: flex; 4 | align-items: center; 5 | gap: 8px; 6 | } 7 | 8 | &__input_wrapper { 9 | display: inline-flex; 10 | align-items: center; 11 | 12 | width: 340px; 13 | height: 40px; 14 | padding: 9px 16px; 15 | background: #ffffff; 16 | border: 1px solid #e5e5e5; 17 | border-radius: 6px; 18 | 19 | @media screen and (max-width: 768px) { 20 | & { 21 | width: 100%; 22 | } 23 | } 24 | 25 | & img { 26 | height: 14px; 27 | aspect-ratio: 1; 28 | 29 | &:nth-child(1) { 30 | margin-right: 10px; 31 | margin-bottom: 3px; 32 | } 33 | 34 | &:last-child { 35 | cursor: pointer; 36 | height: 22px; 37 | } 38 | } 39 | 40 | &.active { 41 | border: 1px solid #ff9933; 42 | outline: 2px solid rgba(255, 153, 51, 0.4); 43 | } 44 | 45 | & input { 46 | border: none; 47 | flex-grow: 1; 48 | height: 20px; 49 | 50 | &:focus, 51 | &:active, 52 | &:focus-visible, 53 | &:focus-within { 54 | outline: none; 55 | } 56 | 57 | &::placeholder { 58 | font-weight: 400; 59 | font-size: 16px; 60 | line-height: 171%; 61 | 62 | color: rgba(34, 34, 34, 0.7); 63 | padding-bottom: 0; 64 | } 65 | } 66 | 67 | &__clear { 68 | border: none; 69 | background: none; 70 | cursor: pointer; 71 | outline: none; 72 | display: flex; 73 | align-items: center; 74 | justify-content: center; 75 | margin-bottom: 0px; 76 | 77 | img { 78 | margin-bottom: 0px !important; 79 | } 80 | } 81 | } 82 | 83 | @media (max-width: 486px) { 84 | width: 100%; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // eslint-disable-next-line @typescript-eslint/triple-slash-reference 3 | /// 4 | /// 5 | 6 | declare namespace NodeJS { 7 | interface ProcessEnv { 8 | readonly NODE_ENV: "development" | "production" | "test"; 9 | readonly PUBLIC_URL: string; 10 | } 11 | } 12 | 13 | declare module "*.avif" { 14 | const src: string; 15 | export default src; 16 | } 17 | 18 | declare module "*.bmp" { 19 | const src: string; 20 | export default src; 21 | } 22 | 23 | declare module "*.gif" { 24 | const src: string; 25 | export default src; 26 | } 27 | 28 | declare module "*.jpg" { 29 | const src: string; 30 | export default src; 31 | } 32 | 33 | declare module "*.jpeg" { 34 | const src: string; 35 | export default src; 36 | } 37 | 38 | declare module "*.png" { 39 | const src: string; 40 | export default src; 41 | } 42 | 43 | declare module "*.webp" { 44 | const src: string; 45 | export default src; 46 | } 47 | 48 | declare module "*.svg" { 49 | import * as React from "react"; 50 | 51 | export const ReactComponent: React.FunctionComponent & { title?: string }>; 52 | 53 | const src: string; 54 | export default src; 55 | } 56 | 57 | declare module "*.module.css" { 58 | const classes: { readonly [key: string]: string }; 59 | export default classes; 60 | } 61 | 62 | declare module "*.module.scss" { 63 | const classes: { readonly [key: string]: string }; 64 | export default classes; 65 | } 66 | 67 | declare module "*.module.sass" { 68 | const classes: { readonly [key: string]: string }; 69 | export default classes; 70 | } 71 | -------------------------------------------------------------------------------- /src/api/user/metadata.ts: -------------------------------------------------------------------------------- 1 | import { getApiUrl, useFetchData } from "../../utils"; 2 | 3 | interface IUseMetadataService { 4 | getUserMetaData: (userId: string) => Promise; 5 | updateUserMetaData: (userId: string, data: string) => Promise; 6 | } 7 | 8 | const useMetadataService = (): IUseMetadataService => { 9 | const fetchData = useFetchData(); 10 | 11 | const getUserMetaData = async (userId: string): Promise => { 12 | const response = await fetchData({ 13 | url: getApiUrl("/api/user/metadata"), 14 | method: "GET", 15 | query: { 16 | userId, 17 | }, 18 | }); 19 | 20 | if (response.ok) { 21 | const body = await response.json(); 22 | 23 | if (body.status === "FEATURE_NOT_ENABLED_ERROR") { 24 | return "FEATURE_NOT_ENABLED_ERROR"; 25 | } 26 | 27 | if (body.status !== "OK") { 28 | return undefined; 29 | } 30 | 31 | return body.data; 32 | } 33 | 34 | return undefined; 35 | }; 36 | 37 | const updateUserMetaData = async (userId: string, data: string) => { 38 | data = data.replaceAll("\n", ""); 39 | const response = await fetchData({ 40 | url: getApiUrl("/api/user/metadata"), 41 | method: "PUT", 42 | config: { 43 | body: JSON.stringify({ 44 | userId, 45 | data, 46 | }), 47 | }, 48 | }); 49 | 50 | if (response.status === 200) { 51 | return await response.json(); 52 | } 53 | 54 | if (response.status === 400) { 55 | throw new Error("Invalid meta data"); 56 | } 57 | 58 | throw new Error("Something went wrong"); 59 | }; 60 | 61 | return { 62 | getUserMetaData, 63 | updateUserMetaData, 64 | }; 65 | }; 66 | 67 | export default useMetadataService; 68 | -------------------------------------------------------------------------------- /src/ui/components/recipePill/recipePill.scss: -------------------------------------------------------------------------------- 1 | .pill { 2 | display: flex; 3 | border-radius: 20px; 4 | padding: 4px 8px; 5 | align-items: center; 6 | width: fit-content; 7 | white-space: nowrap; 8 | @include gap-horizontal(4px); 9 | 10 | &.passwordless { 11 | color: var(--color-passwordless-text); 12 | background-color: var(--color-passwordless-bg); 13 | } 14 | &.emailpassword { 15 | color: var(--color-emailpassword-text); 16 | background-color: var(--color-emailpassword-bg); 17 | } 18 | &.multiple { 19 | color: var(--color-multiple-login-text); 20 | background-color: var(--color-multiple-login-bg); 21 | } 22 | &.thirdparty { 23 | color: var(--color-custom-provider-text); 24 | background-color: var(--color-custom-provider-bg); 25 | max-width: 25ch; 26 | text-overflow: ellipsis; 27 | overflow: hidden; 28 | white-space: nowrap; 29 | .thirdparty-name { 30 | max-width: 10ch; 31 | text-overflow: inherit; 32 | overflow: inherit; 33 | } 34 | &.google { 35 | color: var(--color-google-text); 36 | background-color: var(--color-google-bg); 37 | span { 38 | text-transform: capitalize; 39 | } 40 | } 41 | &.apple { 42 | color: var(--color-apple-text); 43 | background-color: var(--color-apple-bg); 44 | span { 45 | text-transform: capitalize; 46 | } 47 | } 48 | &.github { 49 | color: var(--color-github-text); 50 | background-color: var(--color-github-bg); 51 | span { 52 | text-transform: capitalize; 53 | } 54 | } 55 | &.facebook { 56 | color: var(--color-facebook-text); 57 | background-color: var(--color-facebook-bg); 58 | span { 59 | text-transform: capitalize; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/userDetailForm.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | @import "../../styles/mixin.scss"; 16 | 17 | .user-detail-form { 18 | .input-field-container:not(:last-of-type) { 19 | margin-bottom: 24px; 20 | } 21 | &__header { 22 | font-size: 24px; 23 | } 24 | &__actions { 25 | display: flex; 26 | justify-content: flex-end; 27 | margin-top: 24px; 28 | @include gap-horizontal(24px); 29 | button { 30 | justify-content: center; 31 | font-weight: normal; 32 | padding-top: 10px; 33 | padding-bottom: 10px; 34 | padding-right: 16px; 35 | padding-left: 16px; 36 | } 37 | } 38 | p { 39 | font-size: 14px; 40 | line-height: 24px; 41 | 42 | span { 43 | color: #ed344e; 44 | font-weight: bold; 45 | word-break: break-all; 46 | hyphens: auto; 47 | overflow-wrap: anywhere; 48 | } 49 | } 50 | } 51 | 52 | .phone-input { 53 | margin-top: 12px; 54 | margin-bottom: 8px; 55 | } 56 | 57 | .user-delete-input-container { 58 | margin-top: 8px; 59 | } 60 | -------------------------------------------------------------------------------- /src/ui/components/copyText/CopyText.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | @import "../../styles/mixin.scss"; 16 | 17 | .copy-text { 18 | display: inline-flex; 19 | align-items: center; 20 | max-width: 100%; 21 | .copy-text-text { 22 | @include text-ellipsis(100%); 23 | max-width: 180px; 24 | flex: 1; 25 | padding-right: 4px; 26 | 27 | @media (max-width: 600px) { 28 | max-width: 80px; 29 | } 30 | } 31 | .copy-text-action { 32 | cursor: pointer; 33 | border-radius: 50%; 34 | transition: 0.3s; 35 | &:hover { 36 | background-color: var(--color-copy-box-shadow); 37 | box-shadow: 0px 0px 0px 4px var(--color-copy-box-shadow); 38 | } 39 | } 40 | .copy-text-notification { 41 | position: fixed; 42 | font-size: 12px; 43 | transform: translateY(-50%); 44 | z-index: 1; 45 | 46 | span { 47 | margin: 0px 12px; 48 | white-space: nowrap; 49 | background-color: var(--color-black); 50 | border-color: var(--color-black); 51 | color: var(--color-white); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/thirdPartyProviderButton/thirdPartyProviderButton.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .third-party-provider-cta { 17 | background-color: var(--color-third-party-button-bg); 18 | max-width: fit-content; 19 | border-radius: 4px; 20 | color: var(--color-third-party-button); 21 | font-size: 14px; 22 | font-family: inherit; 23 | border: none; 24 | 25 | &:hover { 26 | background-color: var(--color-third-party-button-container-bg-hover); 27 | } 28 | 29 | &:disabled { 30 | background-color: var(--color-third-party-button-bg); 31 | } 32 | 33 | &__logo-container { 34 | padding: 7px 8px; 35 | display: flex; 36 | align-items: center; 37 | } 38 | 39 | &__divider { 40 | font-family: Menlo, "Source Code Pro", Monaco, Consolas, "Courier New", monospace; 41 | font-size: 13px; 42 | padding: 0 3px; 43 | transform: translateY(-1px); 44 | margin: 0 3px; 45 | color: var(--color-copy-box); 46 | } 47 | 48 | &__icon { 49 | width: 13px; 50 | height: 13px; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ui/components/info-connection/info-connection.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | type InfoConnectionProps = { 17 | connectionURI: string; 18 | }; 19 | 20 | const DEMO_CONNECTION_URIS = ["try.supertokens.io", "try.supertokens.com"]; 21 | 22 | const isDemoConnectionUri = (connectionURI: string) => { 23 | return DEMO_CONNECTION_URIS.some((domains) => connectionURI.includes(domains)); 24 | }; 25 | 26 | export const InfoConnection: React.FC = ({ connectionURI }: InfoConnectionProps) => ( 27 | <> 28 | {isDemoConnectionUri(connectionURI) && ( 29 |
30 |

31 | connectionURI set to {connectionURI} 32 |

33 |

34 | You are connected to an instance of SuperTokens core hosted for demo purposes, this instance should 35 | not be used for production apps. 36 |

37 |
38 | )} 39 | 40 | ); 41 | 42 | export default InfoConnection; 43 | -------------------------------------------------------------------------------- /src/assets/email.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/tenantDetailPanel/tenantDetailPanel.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .panel-root.panel { 17 | padding: 24px; 18 | } 19 | 20 | .panel-root { 21 | &__header { 22 | display: flex; 23 | justify-content: space-between; 24 | 25 | &__title-container { 26 | display: flex; 27 | align-items: center; 28 | gap: 4px; 29 | 30 | h1 { 31 | font-size: 20px; 32 | line-height: 30px; 33 | font-weight: 500; 34 | color: var(--color-black); 35 | } 36 | 37 | &__tooltip { 38 | cursor: pointer; 39 | display: inline-flex; 40 | align-items: center; 41 | justify-content: center; 42 | height: 1em; 43 | width: 1em; 44 | border: 1px solid var(--color-black); 45 | border-radius: 50%; 46 | margin-left: 6px; 47 | img { 48 | height: 1em; 49 | } 50 | } 51 | } 52 | 53 | &__actions { 54 | display: flex; 55 | gap: 16px; 56 | } 57 | } 58 | 59 | &__divider { 60 | display: block; 61 | height: 1px; 62 | background-color: var(--color-border); 63 | margin: 24px -24px; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/addNewProviderDialog/AddNewProviderDialog.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import Button from "../../../button"; 16 | import { Dialog, DialogConfirmText, DialogContent, DialogFooter } from "../../../dialog"; 17 | 18 | export const AddNewProviderDialog = ({ 19 | onCloseDialog, 20 | handleContinue, 21 | }: { 22 | onCloseDialog: () => void; 23 | handleContinue: () => void; 24 | }) => { 25 | return ( 26 | 29 | 30 | 31 | At least one Social / Enterprise login provider is required to enable the third party provider login 32 | method to work. 33 |
34 |
35 | Click “continue” to add a new provider in next step. 36 |
37 | 38 | 43 | 44 | 45 |
46 |
47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/components/nameField/nameField.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import React from "react"; 16 | import InputField from "../../../inputField/InputField"; 17 | import { NameTooltip, UserDetailInfoGridItem } from "../../userDetailInfoGrid"; 18 | 19 | type Props = { 20 | value: string; 21 | fieldName: "first_name" | "last_name"; 22 | label: string; 23 | isEditing: boolean; 24 | onChange: (event: React.ChangeEvent | React.ChangeEvent) => void; 25 | }; 26 | 27 | export const UserDetailNameField: React.FC = ({ value, fieldName, label, isEditing, onChange }: Props) => { 28 | let body: React.ReactNode = value === "" ? "-" : value; 29 | 30 | if (isEditing && value !== "FEATURE_NOT_ENABLED") { 31 | body = ( 32 | 38 | ); 39 | } 40 | 41 | return ( 42 | } 46 | /> 47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /src/ui/components/nativeSelect/NativeSelect.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import "./nativeSelect.scss"; 17 | 18 | type NativeSelectProps = React.SelectHTMLAttributes & { 19 | options: string[]; 20 | label?: string; 21 | isRequired?: boolean; 22 | }; 23 | 24 | export const NativeSelect = ({ options, label, isRequired, ...rest }: NativeSelectProps) => { 25 | return ( 26 |
27 | {label && ( 28 | 34 | )} 35 |
36 | 52 |
53 |
54 | ); 55 | }; 56 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/loginMethods/components/dropDown.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from "react"; 2 | import { getImageUrl, useClickOutside } from "../../../../../utils"; 3 | import "./dropdown.scss"; 4 | 5 | type DropDOwnProps = { 6 | onEdit: () => void; 7 | onUnlink: () => void | null; 8 | onDelete: () => void | null; 9 | showUnlink: boolean; 10 | }; 11 | 12 | export const DropDown = ({ onEdit, onUnlink, onDelete, showUnlink }: DropDOwnProps) => { 13 | const [open, setOpen] = useState(false); 14 | const [hover, setHover] = useState(false); 15 | const ref = useRef(null); 16 | useClickOutside(ref, () => setOpen(false)); 17 | const close = (func: () => void | null) => { 18 | setOpen(false); 19 | func(); 20 | }; 21 | return ( 22 |
setHover(true)} 26 | onMouseLeave={() => setHover(false)}> 27 |
setOpen(!open)}> 30 | {(open || hover) && } 31 | {!(open || hover) && } 32 |
33 |
34 |
close(onEdit)}> 35 | {" "} 39 | Edit 40 |
41 | {showUnlink && ( 42 |
close(onUnlink)}> 43 | {" "} 47 | Unlink 48 |
49 | )} 50 |
close(onDelete)}> 51 | {" "} 55 | Delete 56 |
57 |
58 |
59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/TenantDetailContext.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { createContext, useContext } from "react"; 17 | import { TenantInfo } from "../../../../api/tenants/types"; 18 | 19 | type TenantDetailContextType = { 20 | tenantInfo: TenantInfo; 21 | refetchTenant: () => Promise; 22 | }; 23 | 24 | const TenantDetailContext = createContext(undefined); 25 | 26 | export const TenantDetailContextProvider = ({ 27 | children, 28 | tenantInfo, 29 | refetchTenant, 30 | }: { 31 | children: React.ReactNode; 32 | tenantInfo: TenantInfo; 33 | refetchTenant: () => Promise; 34 | }) => { 35 | return ( 36 | 41 | {children} 42 | 43 | ); 44 | }; 45 | 46 | export const useTenantDetailContext = () => { 47 | const context = useContext(TenantDetailContext); 48 | if (context === undefined) { 49 | throw new Error("useTenantDetailContext must be used within a TenantDetailContextProvider"); 50 | } 51 | return context; 52 | }; 53 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/thirdPartyProviderInput/thirdPartyProviderInput.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .third-party-provider-input-container { 17 | display: flex; 18 | width: 100%; 19 | gap: 20px; 20 | 21 | @media screen and (max-width: 768px) { 22 | flex-direction: column; 23 | gap: 12px; 24 | } 25 | 26 | &__label { 27 | font-family: inherit; 28 | font-weight: 500; 29 | font-size: 14px; 30 | color: var(--color-secondary-text); 31 | min-width: max-content; 32 | 33 | @media screen and (max-width: 768px) { 34 | min-width: unset; 35 | } 36 | } 37 | 38 | &__required { 39 | color: var(--color-required); 40 | } 41 | 42 | &__label-container { 43 | display: flex; 44 | gap: 6px; 45 | height: fit-content; 46 | align-items: center; 47 | margin-top: 10px; 48 | } 49 | 50 | .input-field-container { 51 | width: 100%; 52 | /** Remove the box from the error styles for input */ 53 | .block-small { 54 | padding: 0px; 55 | } 56 | 57 | .block-error { 58 | background-color: transparent; 59 | } 60 | 61 | .input-field-error { 62 | margin-top: 4px; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ui/components/deleteCrossButton/DeleteCrossButton.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | import { useEffect, useState } from "react"; 16 | import { ReactComponent as CloseIconActive } from "../../../assets/close-active.svg"; 17 | import { ReactComponent as CloseIconDefault } from "../../../assets/close-inactive.svg"; 18 | 19 | import "./deleteCrossButton.scss"; 20 | 21 | export const DeleteCrossButton = ({ 22 | onClick, 23 | label, 24 | disabled, 25 | }: { 26 | onClick: () => void; 27 | label: string; 28 | disabled?: boolean; 29 | }) => { 30 | const [isHovered, setIsHovered] = useState(false); 31 | 32 | useEffect(() => { 33 | if (disabled) { 34 | setIsHovered(false); 35 | } 36 | }, [disabled]); 37 | 38 | return ( 39 | 50 | ); 51 | }; 52 | -------------------------------------------------------------------------------- /src/assets/info-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ui/components/tenants/tenantDetail/editPluginPropertyDialog/editPluginPropertyDialog.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .dialog-container-650 { 17 | max-width: 650px; 18 | } 19 | 20 | .command-container { 21 | margin-top: 0px; 22 | display: flex; 23 | padding-block: 6px; 24 | padding-inline: 8px 4px; 25 | border: 1px solid var(--color-border-command); 26 | border-radius: 6px; 27 | white-space: break-spaces; 28 | 29 | .clipboard-btn-container { 30 | height: 24px; 31 | min-width: 24px; 32 | border-radius: 50%; 33 | transition: 0.1s all ease-in-out; 34 | cursor: pointer; 35 | 36 | &:hover { 37 | background: rgba(217, 217, 217, 0.6); 38 | } 39 | 40 | .clipboard-icon { 41 | width: 12px; 42 | height: 14px; 43 | } 44 | } 45 | 46 | code.command { 47 | word-break: break-word; 48 | font-size: 13px; 49 | line-height: 1.6; 50 | color: var(--color-command); 51 | flex: 1; 52 | max-height: 300px; 53 | overflow-y: scroll; 54 | 55 | .hljs-string { 56 | color: inherit; 57 | } 58 | } 59 | 60 | .tooltip-container { 61 | height: fit-content; 62 | 63 | .tooltip-container__popup { 64 | padding: 3px 8px; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ui/components/userDetail/userRoles/userRolesList.scss: -------------------------------------------------------------------------------- 1 | .user-roles-list-wrapper { 2 | .shimmer-container { 3 | display: flex; 4 | flex-direction: column; 5 | gap: 10px; 6 | width: 100%; 7 | margin-top: 5px; 8 | } 9 | 10 | & > .roles-list-container { 11 | display: flex; 12 | justify-content: flex-start; 13 | gap: 14px; 14 | flex-wrap: wrap; 15 | align-items: center; 16 | border-top: 1px solid var(--color-border); 17 | padding-top: 20px; 18 | margin-top: 20px; 19 | 20 | .no-roles-found { 21 | padding: 20px 0px; 22 | font-size: 14px; 23 | color: var(--color-black); 24 | } 25 | 26 | .add-role-btn { 27 | display: flex; 28 | padding: 2px 8px; 29 | align-items: center; 30 | gap: 10px; 31 | border-radius: 6px; 32 | border: 1px solid rgb(217, 217, 217); 33 | background: rgb(249, 249, 249); 34 | 35 | color: var(--color-secondary-tex); 36 | font-size: 14px; 37 | font-style: normal; 38 | font-weight: 400; 39 | line-height: 21px; 40 | 41 | & > svg { 42 | fill: #6e6a65; 43 | } 44 | 45 | &:hover:not([data-disable-hover="true"]) { 46 | border: 1px solid rgba(0, 122, 255, 0.5); 47 | 48 | color: var(--color-secondary); 49 | font-size: 14px; 50 | 51 | & > svg { 52 | fill: var(--color-secondary); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | .select-tenantId-container { 60 | color: var(--color-secondary-text); 61 | font-size: 14px; 62 | font-style: normal; 63 | font-weight: 400; 64 | line-height: 23px; 65 | 66 | display: flex; 67 | align-items: center; 68 | gap: 10px; 69 | flex-wrap: wrap; 70 | margin-top: -32px; 71 | 72 | & > span { 73 | font-weight: 500; 74 | } 75 | 76 | @media (max-width: 440px) { 77 | font-size: 12px; 78 | line-height: 18px; 79 | } 80 | } 81 | 82 | .feature-not-enabled { 83 | margin-top: -10px; 84 | color: #6e6a65; 85 | font-size: 14px; 86 | } 87 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/ui/components/nativeSelect/nativeSelect.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .select-label { 17 | color: var(--color-secondary-text); 18 | font-weight: 500; 19 | margin-bottom: 12px; 20 | } 21 | 22 | .select-label-required { 23 | color: var(--color-error); 24 | margin: 0px 4px; 25 | } 26 | 27 | .select-container { 28 | display: flex; 29 | flex-direction: column; 30 | 31 | .select-wrapper { 32 | width: 100%; 33 | position: relative; 34 | select { 35 | width: 100%; 36 | padding: 9px 13px; 37 | border: 1px solid var(--color-border); 38 | background-color: var(--color-input-unfocused); 39 | border-radius: 6px; 40 | font-size: 14px; 41 | color: var(--color-black); 42 | appearance: none; /* Remove default styles */ 43 | -webkit-appearance: none; /* For Safari */ 44 | -moz-appearance: none; /* For Firefox */ 45 | } 46 | 47 | &::after { 48 | content: "\2304"; /* Unicode character for the down arrow */ 49 | position: absolute; 50 | top: 37%; 51 | right: 10px; 52 | font-size: 18px; 53 | font-weight: 600; 54 | transform: translateY(-50%); 55 | pointer-events: none; 56 | color: var(--color-black); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/assets/provider-apple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/ui/components/userroles/components/dialogs/AssignRoleConfimation.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import Button from "../../../button"; 17 | import { Dialog, DialogContent, DialogFooter } from "../../../dialog"; 18 | 19 | export default function AssignRoleConfirmation({ 20 | onCloseDialog, 21 | assignRoleToUser, 22 | isAddingRoles, 23 | role, 24 | }: { 25 | onCloseDialog: () => void; 26 | role: string; 27 | isAddingRoles: boolean; 28 | assignRoleToUser: (role: string) => void; 29 | }) { 30 | return ( 31 | 34 | 35 |

36 | Please confirm to add {role} role to this 37 | user. 38 |

39 | 40 | 45 | 51 | 52 |
53 |
54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /src/ui/pages/tenants/index.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | .tenants-container { 17 | max-width: var(--container-width); 18 | height: 100%; 19 | padding: 72px 0px 0px; 20 | margin: auto; 21 | margin-bottom: 36px; 22 | 23 | .tenants-title { 24 | font-size: 28px; 25 | line-height: 34px; 26 | color: var(--color-black); 27 | margin-bottom: 16px; 28 | font-weight: 500; 29 | } 30 | 31 | .tenants-subtitle { 32 | color: var(--color-secondary-text); 33 | margin-bottom: 40px; 34 | } 35 | } 36 | 37 | @media (max-width: 1024px) { 38 | .tenants-container { 39 | padding: 72px 40px 48px; 40 | max-width: 100%; 41 | } 42 | } 43 | 44 | @media (max-width: 480px) { 45 | .tenants-container { 46 | padding: 72px 18px 48px; 47 | max-width: 100%; 48 | } 49 | } 50 | 51 | .search-container { 52 | display: flex; 53 | justify-content: space-between; 54 | align-items: flex-start; 55 | margin-bottom: 26px; 56 | 57 | @media (max-width: 768px) { 58 | gap: 16px; 59 | #create-tenant { 60 | min-width: fit-content; 61 | } 62 | } 63 | 64 | @media (max-width: 486px) { 65 | flex-direction: column; 66 | #create-tenant { 67 | width: 100%; 68 | justify-content: center; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/ui/components/authWrapper/index.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { useEffect, useState } from "react"; 17 | import { StorageKeys } from "../../../constants"; 18 | import { localStorageHandler } from "../../../services/storage"; 19 | import Auth from "../auth/Auth"; 20 | 21 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 22 | export default function AuthWrapper(props: { children: any }) { 23 | const [shouldShowAuthForm, setShouldShowAuthForm] = useState(false); 24 | const [isLoading, setIsLoading] = useState(true); 25 | 26 | useEffect(() => { 27 | const apiKey = localStorageHandler.getItem(StorageKeys.AUTH_KEY); 28 | const _shouldShowAuthForm = apiKey === undefined; 29 | 30 | if (_shouldShowAuthForm) { 31 | localStorageHandler.removeItem(StorageKeys.AUTH_KEY); 32 | localStorageHandler.removeItem(StorageKeys.EMAIL); 33 | } 34 | 35 | setShouldShowAuthForm(_shouldShowAuthForm); 36 | setIsLoading(false); 37 | }, []); 38 | 39 | if (isLoading) { 40 | return <>; 41 | } 42 | 43 | if (shouldShowAuthForm) { 44 | return ( 45 | { 47 | setShouldShowAuthForm(false); 48 | }} 49 | /> 50 | ); 51 | } 52 | 53 | return props.children; 54 | } 55 | -------------------------------------------------------------------------------- /src/assets/help-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ui/components/footer/footer.tsx: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | 16 | import { getImageUrl } from "../../../utils"; 17 | import "./footer.scss"; 18 | 19 | export type FooterProps = { 20 | horizontalAlignment?: "left" | "center" | "right"; 21 | verticalAlignment?: "top" | "bottom" | "center"; 22 | colorMode?: "light" | "dark"; 23 | size?: "normal" | "large"; 24 | }; 25 | 26 | export const LOGO_DARK = getImageUrl("ST_full_logo_dark_theme.svg"); 27 | export const LOGO_LIGHT = getImageUrl("ST_icon_light_theme.svg"); 28 | export const LOGO_ICON_LIGHT = getImageUrl("ST_full_logo_light_theme.svg"); 29 | export const LOGO_ICON_DARK = getImageUrl("ST_icon_dark_theme.svg"); 30 | 31 | export const Footer = ({ horizontalAlignment, verticalAlignment, colorMode, size }: FooterProps) => { 32 | return ( 33 |
35 | 40 | Supertokens 44 | 45 |
46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /src/ui/components/loader/loader.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. 2 | * 3 | * This software is licensed under the Apache License, Version 2.0 (the 4 | * "License") as published by the Apache Software Foundation. 5 | * 6 | * You may not use this file except in compliance with the License. You may 7 | * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and limitations 13 | * under the License. 14 | */ 15 | .loader-container { 16 | min-height: 80vh; 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | } 21 | 22 | .full-screen-loading-overlay { 23 | position: fixed; 24 | top: 0; 25 | left: 0; 26 | right: 0; 27 | bottom: 0; 28 | background-color: rgba(0, 0, 0, 0.4); 29 | z-index: 1; 30 | display: flex; 31 | justify-content: center; 32 | align-items: center; 33 | } 34 | 35 | .loader-wrapper { 36 | background-color: var(--color-window-bg); 37 | padding: 2px; 38 | display: flex; 39 | border-radius: 50%; 40 | } 41 | 42 | .loader { 43 | border: 16px solid #f3f3f3; /* Light grey */ 44 | border-top: 16px solid #ff9933; /* Blue */ 45 | border-radius: 50%; 46 | width: 60px; 47 | height: 60px; 48 | animation: spin 2s linear infinite; 49 | } 50 | 51 | @keyframes spin { 52 | 0% { 53 | transform: rotate(0deg); 54 | } 55 | 100% { 56 | transform: rotate(360deg); 57 | } 58 | } 59 | 60 | @-webkit-keyframes spin { 61 | 0% { 62 | -webkit-transform: rotate(0deg); 63 | } 64 | 100% { 65 | -webkit-transform: rotate(360deg); 66 | } 67 | } 68 | 69 | @-moz-keyframes spin { 70 | 0% { 71 | -moz-transform: rotate(0deg); 72 | } 73 | 100% { 74 | -moz-transform: rotate(360deg); 75 | } 76 | } 77 | --------------------------------------------------------------------------------