diff --git a/Makefile b/Makefile deleted file mode 100644 index abbfb62..0000000 --- a/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -gen: - @protoc --proto_path=proto --openapi_out=proto/user/v1 \ - proto/user/v1/user.proto - @pnpm openapi-generator-cli generate -g typescript-axios -i ./proto/user/v1/openapi.yaml -o ./proto/user/v1/api diff --git a/configutation.ts b/configutation.ts deleted file mode 100644 index 749ca42..0000000 --- a/configutation.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {Configuration, UserServiceApi} from "./proto/user/v1/api"; - -const configuration = new Configuration({ - basePath: "http://localhost:60001" -}) - -const userApi = new UserServiceApi(configuration); - -export {userApi}; \ No newline at end of file diff --git a/package.json b/package.json index 1771360..4c3cb17 100644 --- a/package.json +++ b/package.json @@ -6,27 +6,29 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "gen": "openapi-generator-cli generate -g typescript-axios -i ./proto/user/v1/openapi.yaml -o ./proto/user/v1/api" }, "dependencies": { - "@mantine/core": "^7.16.3", - "@mantine/dropzone": "^7.16.3", - "@mantine/form": "^7.16.3", - "@mantine/hooks": "^7.16.3", - "@reduxjs/toolkit": "^2.5.1", + "@mantine/core": "^7.17.0", + "@mantine/dropzone": "^7.17.0", + "@mantine/form": "^7.17.0", + "@mantine/hooks": "^7.17.0", "@tabler/icons-react": "^3.30.0", - "@tanstack/react-query": "^5.66.3", + "@tanstack/react-query": "^5.66.7", "axios": "^1.7.9", - "next": "15.1.0", + "jsonwebtoken": "^9.0.2", + "next": "^15.1.7", "react": "^19.0.0", "react-dom": "^19.0.0", "redux-query": "3.6.1-rc.2" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.16.3", + "@types/jsonwebtoken": "^9.0.9", "@types/node": "^20.17.19", - "@types/react": "^19.0.9", - "@types/react-dom": "^19.0.3", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", "postcss": "^8.5.2", "postcss-preset-mantine": "^1.17.0", "postcss-simple-vars": "^7.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09f73f9..536ab0b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,32 +6,32 @@ settings: dependencies: '@mantine/core': - specifier: ^7.16.3 - version: 7.16.3(@mantine/hooks@7.16.3)(@types/react@19.0.9)(react-dom@19.0.0)(react@19.0.0) + specifier: ^7.17.0 + version: 7.17.0(@mantine/hooks@7.17.0)(@types/react@19.0.10)(react-dom@19.0.0)(react@19.0.0) '@mantine/dropzone': - specifier: ^7.16.3 - version: 7.16.3(@mantine/core@7.16.3)(@mantine/hooks@7.16.3)(react-dom@19.0.0)(react@19.0.0) + specifier: ^7.17.0 + version: 7.17.0(@mantine/core@7.17.0)(@mantine/hooks@7.17.0)(react-dom@19.0.0)(react@19.0.0) '@mantine/form': - specifier: ^7.16.3 - version: 7.16.3(react@19.0.0) + specifier: ^7.17.0 + version: 7.17.0(react@19.0.0) '@mantine/hooks': - specifier: ^7.16.3 - version: 7.16.3(react@19.0.0) - '@reduxjs/toolkit': - specifier: ^2.5.1 - version: 2.5.1(react@19.0.0) + specifier: ^7.17.0 + version: 7.17.0(react@19.0.0) '@tabler/icons-react': specifier: ^3.30.0 version: 3.30.0(react@19.0.0) '@tanstack/react-query': - specifier: ^5.66.3 - version: 5.66.3(react@19.0.0) + specifier: ^5.66.7 + version: 5.66.7(react@19.0.0) axios: specifier: ^1.7.9 version: 1.7.9 + jsonwebtoken: + specifier: ^9.0.2 + version: 9.0.2 next: - specifier: 15.1.0 - version: 15.1.0(react-dom@19.0.0)(react@19.0.0) + specifier: ^15.1.7 + version: 15.1.7(react-dom@19.0.0)(react@19.0.0) react: specifier: ^19.0.0 version: 19.0.0 @@ -46,15 +46,18 @@ devDependencies: '@openapitools/openapi-generator-cli': specifier: ^2.16.3 version: 2.16.3 + '@types/jsonwebtoken': + specifier: ^9.0.9 + version: 9.0.9 '@types/node': specifier: ^20.17.19 version: 20.17.19 '@types/react': - specifier: ^19.0.9 - version: 19.0.9 + specifier: ^19.0.10 + version: 19.0.10 '@types/react-dom': - specifier: ^19.0.3 - version: 19.0.3(@types/react@19.0.9) + specifier: ^19.0.4 + version: 19.0.4(@types/react@19.0.10) postcss: specifier: ^8.5.2 version: 8.5.2 @@ -310,43 +313,43 @@ packages: engines: {node: '>=8'} dev: true - /@mantine/core@7.16.3(@mantine/hooks@7.16.3)(@types/react@19.0.9)(react-dom@19.0.0)(react@19.0.0): - resolution: {integrity: sha512-cxhIpfd2i0Zmk9TKdejYAoIvWouMGhzK3OOX+VRViZ5HEjnTQCGl2h3db56ThqB6NfVPCno6BPbt5lwekTtmuQ==} + /@mantine/core@7.17.0(@mantine/hooks@7.17.0)(@types/react@19.0.10)(react-dom@19.0.0)(react@19.0.0): + resolution: {integrity: sha512-AU5UFewUNzBCUXIq5Jk6q402TEri7atZW61qHW6P0GufJ2W/JxGHRvgmHOVHTVIcuWQRCt9SBSqZoZ/vHs9LhA==} peerDependencies: - '@mantine/hooks': 7.16.3 + '@mantine/hooks': 7.17.0 react: ^18.x || ^19.x react-dom: ^18.x || ^19.x dependencies: '@floating-ui/react': 0.26.28(react-dom@19.0.0)(react@19.0.0) - '@mantine/hooks': 7.16.3(react@19.0.0) + '@mantine/hooks': 7.17.0(react@19.0.0) clsx: 2.1.1 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) react-number-format: 5.4.3(react-dom@19.0.0)(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0) - react-textarea-autosize: 8.5.6(@types/react@19.0.9)(react@19.0.0) - type-fest: 4.34.1 + react-remove-scroll: 2.6.3(@types/react@19.0.10)(react@19.0.0) + react-textarea-autosize: 8.5.6(@types/react@19.0.10)(react@19.0.0) + type-fest: 4.35.0 transitivePeerDependencies: - '@types/react' dev: false - /@mantine/dropzone@7.16.3(@mantine/core@7.16.3)(@mantine/hooks@7.16.3)(react-dom@19.0.0)(react@19.0.0): - resolution: {integrity: sha512-JWKmRMuV0DfgIQWvvtRfokaIopezg2AwxxcXrHs5xxxN1EfiTQWB+aQjz0ISwcAk1gtjLEKHowqsBNbna+BEKw==} + /@mantine/dropzone@7.17.0(@mantine/core@7.17.0)(@mantine/hooks@7.17.0)(react-dom@19.0.0)(react@19.0.0): + resolution: {integrity: sha512-1BGOH/Fs1xxsVl6JUxFAElwqdmtj1nrzc7QSV3vs3xh7zAIAH6wqeor8j8+yycxz4lCfehHSaVAyDDv3AFsX8w==} peerDependencies: - '@mantine/core': 7.16.3 - '@mantine/hooks': 7.16.3 + '@mantine/core': 7.17.0 + '@mantine/hooks': 7.17.0 react: ^18.x || ^19.x react-dom: ^18.x || ^19.x dependencies: - '@mantine/core': 7.16.3(@mantine/hooks@7.16.3)(@types/react@19.0.9)(react-dom@19.0.0)(react@19.0.0) - '@mantine/hooks': 7.16.3(react@19.0.0) + '@mantine/core': 7.17.0(@mantine/hooks@7.17.0)(@types/react@19.0.10)(react-dom@19.0.0)(react@19.0.0) + '@mantine/hooks': 7.17.0(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) react-dropzone-esm: 15.2.0(react@19.0.0) dev: false - /@mantine/form@7.16.3(react@19.0.0): - resolution: {integrity: sha512-GqomUG2Ri5adxYsTU1S5IhKRPcqTG5JkPvMERns8PQAcUz/lvzsnk3wY1v4K5CEbCAdpimle4bSsZTM9g697vg==} + /@mantine/form@7.17.0(react@19.0.0): + resolution: {integrity: sha512-LONdeb+wL8h9fvyQ339ZFLxqrvYff+b+H+kginZhnr45OBTZDLXNVAt/YoKVFEkynF9WDJjdBVrXKcOZvPgmrA==} peerDependencies: react: ^18.x || ^19.x dependencies: @@ -355,8 +358,8 @@ packages: react: 19.0.0 dev: false - /@mantine/hooks@7.16.3(react@19.0.0): - resolution: {integrity: sha512-B94FBWk5Sc81tAjV+B3dGh/gKzfqzpzVC/KHyBRWOOyJRqeeRbI/FAaJo4zwppyQo1POSl5ArdyjtDRrRIj2SQ==} + /@mantine/hooks@7.17.0(react@19.0.0): + resolution: {integrity: sha512-vo3K49mLy1nJ8LQNb5KDbJgnX0xwt3Y8JOF3ythjB5LEFMptdLSSgulu64zj+QHtzvffFCsMb05DbTLLpVP/JQ==} peerDependencies: react: ^18.x || ^19.x dependencies: @@ -426,12 +429,12 @@ packages: - encoding dev: true - /@next/env@15.1.0: - resolution: {integrity: sha512-UcCO481cROsqJuszPPXJnb7GGuLq617ve4xuAyyNG4VSSocJNtMU5Fsx+Lp6mlN8c7W58aZLc5y6D/2xNmaK+w==} + /@next/env@15.1.7: + resolution: {integrity: sha512-d9jnRrkuOH7Mhi+LHav2XW91HOgTAWHxjMPkXMGBc9B2b7614P7kjt8tAplRvJpbSt4nbO1lugcT/kAaWzjlLQ==} dev: false - /@next/swc-darwin-arm64@15.1.0: - resolution: {integrity: sha512-ZU8d7xxpX14uIaFC3nsr4L++5ZS/AkWDm1PzPO6gD9xWhFkOj2hzSbSIxoncsnlJXB1CbLOfGVN4Zk9tg83PUw==} + /@next/swc-darwin-arm64@15.1.7: + resolution: {integrity: sha512-hPFwzPJDpA8FGj7IKV3Yf1web3oz2YsR8du4amKw8d+jAOHfYHYFpMkoF6vgSY4W6vB29RtZEklK9ayinGiCmQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -439,8 +442,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@15.1.0: - resolution: {integrity: sha512-DQ3RiUoW2XC9FcSM4ffpfndq1EsLV0fj0/UY33i7eklW5akPUCo6OX2qkcLXZ3jyPdo4sf2flwAED3AAq3Om2Q==} + /@next/swc-darwin-x64@15.1.7: + resolution: {integrity: sha512-2qoas+fO3OQKkU0PBUfwTiw/EYpN+kdAx62cePRyY1LqKtP09Vp5UcUntfZYajop5fDFTjSxCHfZVRxzi+9FYQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -448,8 +451,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@15.1.0: - resolution: {integrity: sha512-M+vhTovRS2F//LMx9KtxbkWk627l5Q7AqXWWWrfIzNIaUFiz2/NkOFkxCFyNyGACi5YbA8aekzCLtbDyfF/v5Q==} + /@next/swc-linux-arm64-gnu@15.1.7: + resolution: {integrity: sha512-sKLLwDX709mPdzxMnRIXLIT9zaX2w0GUlkLYQnKGoXeWUhcvpCrK+yevcwCJPdTdxZEUA0mOXGLdPsGkudGdnA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -457,8 +460,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@15.1.0: - resolution: {integrity: sha512-Qn6vOuwaTCx3pNwygpSGtdIu0TfS1KiaYLYXLH5zq1scoTXdwYfdZtwvJTpB1WrLgiQE2Ne2kt8MZok3HlFqmg==} + /@next/swc-linux-arm64-musl@15.1.7: + resolution: {integrity: sha512-zblK1OQbQWdC8fxdX4fpsHDw+VSpBPGEUX4PhSE9hkaWPrWoeIJn+baX53vbsbDRaDKd7bBNcXRovY1hEhFd7w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -466,8 +469,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@15.1.0: - resolution: {integrity: sha512-yeNh9ofMqzOZ5yTOk+2rwncBzucc6a1lyqtg8xZv0rH5znyjxHOWsoUtSq4cUTeeBIiXXX51QOOe+VoCjdXJRw==} + /@next/swc-linux-x64-gnu@15.1.7: + resolution: {integrity: sha512-GOzXutxuLvLHFDAPsMP2zDBMl1vfUHHpdNpFGhxu90jEzH6nNIgmtw/s1MDwpTOiM+MT5V8+I1hmVFeAUhkbgQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -475,8 +478,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@15.1.0: - resolution: {integrity: sha512-t9IfNkHQs/uKgPoyEtU912MG6a1j7Had37cSUyLTKx9MnUpjj+ZDKw9OyqTI9OwIIv0wmkr1pkZy+3T5pxhJPg==} + /@next/swc-linux-x64-musl@15.1.7: + resolution: {integrity: sha512-WrZ7jBhR7ATW1z5iEQ0ZJfE2twCNSXbpCSaAunF3BKcVeHFADSI/AW1y5Xt3DzTqPF1FzQlwQTewqetAABhZRQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -484,8 +487,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@15.1.0: - resolution: {integrity: sha512-WEAoHyG14t5sTavZa1c6BnOIEukll9iqFRTavqRVPfYmfegOAd5MaZfXgOGG6kGo1RduyGdTHD4+YZQSdsNZXg==} + /@next/swc-win32-arm64-msvc@15.1.7: + resolution: {integrity: sha512-LDnj1f3OVbou1BqvvXVqouJZKcwq++mV2F+oFHptToZtScIEnhNRJAhJzqAtTE2dB31qDYL45xJwrc+bLeKM2Q==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -493,8 +496,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@15.1.0: - resolution: {integrity: sha512-J1YdKuJv9xcixzXR24Dv+4SaDKc2jj31IVUEMdO5xJivMTXuE6MAdIi4qPjSymHuFG8O5wbfWKnhJUcHHpj5CA==} + /@next/swc-win32-x64-msvc@15.1.7: + resolution: {integrity: sha512-dC01f1quuf97viOfW05/K8XYv2iuBgAxJZl7mbCKEjMgdQl5JjAKJ0D2qMKZCgPWDeFbFT0Q0nYWwytEW0DWTQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -570,24 +573,6 @@ packages: - supports-color dev: true - /@reduxjs/toolkit@2.5.1(react@19.0.0): - resolution: {integrity: sha512-UHhy3p0oUpdhnSxyDjaRDYaw8Xra75UiLbCiRozVPHjfDwNYkh0TsVm/1OmTW8Md+iDAJmYPWUKMvsMc2GtpNg==} - peerDependencies: - react: ^16.9.0 || ^17.0.0 || ^18 || ^19 - react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 - peerDependenciesMeta: - react: - optional: true - react-redux: - optional: true - dependencies: - immer: 10.1.1 - react: 19.0.0 - redux: 5.0.1 - redux-thunk: 3.1.0(redux@5.0.1) - reselect: 5.1.1 - dev: false - /@swc/counter@0.1.3: resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} dev: false @@ -611,16 +596,16 @@ packages: resolution: {integrity: sha512-c8OKLM48l00u9TFbh2qhSODMONIzML8ajtCyq95rW8vzkWcBrKRPM61tdkThz2j4kd5u17srPGIjqdeRUZdfdw==} dev: false - /@tanstack/query-core@5.66.3: - resolution: {integrity: sha512-+2iDxH7UFdtwcry766aJszGmbByQDIzTltJ3oQAZF9bhCxHCIN3yDwHa6qDCZxcpMGvUphCRx/RYJvLbM8mucQ==} + /@tanstack/query-core@5.66.4: + resolution: {integrity: sha512-skM/gzNX4shPkqmdTCSoHtJAPMTtmIJNS0hE+xwTTUVYwezArCT34NMermABmBVUg5Ls5aiUXEDXfqwR1oVkcA==} dev: false - /@tanstack/react-query@5.66.3(react@19.0.0): - resolution: {integrity: sha512-sWMvxZ5VugPDgD1CzP7f0s9yFvjcXP3FXO5IVV2ndXlYqUCwykU8U69Kk05Qn5UvGRqB/gtj4J7vcTC6vtLHtQ==} + /@tanstack/react-query@5.66.7(react@19.0.0): + resolution: {integrity: sha512-qd3q/tUpF2K1xItfPZddk1k/8pSXnovg41XyCqJgPoyYEirMBtB0sVEVVQ/CsAOngzgWtBPXimVf4q4kM9uO6A==} peerDependencies: react: ^18 || ^19 dependencies: - '@tanstack/query-core': 5.66.3 + '@tanstack/query-core': 5.66.4 react: 19.0.0 dev: false @@ -628,22 +613,33 @@ packages: resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} dev: true + /@types/jsonwebtoken@9.0.9: + resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==} + dependencies: + '@types/ms': 2.1.0 + '@types/node': 20.17.19 + dev: true + + /@types/ms@2.1.0: + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + dev: true + /@types/node@20.17.19: resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} dependencies: undici-types: 6.19.8 dev: true - /@types/react-dom@19.0.3(@types/react@19.0.9): - resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} + /@types/react-dom@19.0.4(@types/react@19.0.10): + resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} peerDependencies: '@types/react': ^19.0.0 dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 dev: true - /@types/react@19.0.9: - resolution: {integrity: sha512-FedNTYgmMwSZmD1Sru/W1gJKuiYCN/3SuBkmZkcxX+FpO5zL76B22A9YNfAKg4HQO3Neh/30AiynP6BELdU0qQ==} + /@types/react@19.0.10: + resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==} dependencies: csstype: 3.1.3 @@ -728,6 +724,10 @@ packages: fill-range: 7.1.1 dev: true + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: false + /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -772,8 +772,8 @@ packages: engines: {node: '>= 6'} dev: true - /caniuse-lite@1.0.30001699: - resolution: {integrity: sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==} + /caniuse-lite@1.0.30001700: + resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} dev: false /chalk@4.1.2: @@ -986,6 +986,12 @@ packages: wcwidth: 1.0.1 dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -1259,10 +1265,6 @@ packages: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: true - /immer@10.1.1: - resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==} - dev: false - /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true @@ -1380,11 +1382,70 @@ packages: resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} dev: false + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.1 + dev: false + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + /klona@2.0.6: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} dev: false + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: false + + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: false + + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: false + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: false + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: false + + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: false + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true @@ -1464,7 +1525,6 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true /mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -1480,8 +1540,8 @@ packages: engines: {node: '>= 0.4.0'} dev: true - /next@15.1.0(react-dom@19.0.0)(react@19.0.0): - resolution: {integrity: sha512-QKhzt6Y8rgLNlj30izdMbxAwjHMFANnLwDwZ+WQh5sMhyt4lEBqDK9QpvWHtIM4rINKPoJ8aiRZKg5ULSybVHw==} + /next@15.1.7(react-dom@19.0.0)(react@19.0.0): + resolution: {integrity: sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -1501,24 +1561,24 @@ packages: sass: optional: true dependencies: - '@next/env': 15.1.0 + '@next/env': 15.1.7 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001699 + caniuse-lite: 1.0.30001700 postcss: 8.4.31 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) styled-jsx: 5.1.6(react@19.0.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.1.0 - '@next/swc-darwin-x64': 15.1.0 - '@next/swc-linux-arm64-gnu': 15.1.0 - '@next/swc-linux-arm64-musl': 15.1.0 - '@next/swc-linux-x64-gnu': 15.1.0 - '@next/swc-linux-x64-musl': 15.1.0 - '@next/swc-win32-arm64-msvc': 15.1.0 - '@next/swc-win32-x64-msvc': 15.1.0 + '@next/swc-darwin-arm64': 15.1.7 + '@next/swc-darwin-x64': 15.1.7 + '@next/swc-linux-arm64-gnu': 15.1.7 + '@next/swc-linux-arm64-musl': 15.1.7 + '@next/swc-linux-x64-gnu': 15.1.7 + '@next/swc-linux-x64-musl': 15.1.7 + '@next/swc-win32-arm64-msvc': 15.1.7 + '@next/swc-win32-x64-msvc': 15.1.7 sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' @@ -1574,8 +1634,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /pac-proxy-agent@7.1.0: - resolution: {integrity: sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==} + /pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} engines: {node: '>= 14'} dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 @@ -1713,7 +1773,7 @@ packages: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 - pac-proxy-agent: 7.1.0 + pac-proxy-agent: 7.2.0 proxy-from-env: 1.1.0 socks-proxy-agent: 8.0.5 transitivePeerDependencies: @@ -1760,7 +1820,7 @@ packages: react-dom: 19.0.0(react@19.0.0) dev: false - /react-remove-scroll-bar@2.3.8(@types/react@19.0.9)(react@19.0.0): + /react-remove-scroll-bar@2.3.8(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} peerDependencies: @@ -1770,13 +1830,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 - react-style-singleton: 2.2.3(@types/react@19.0.9)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) tslib: 2.8.1 dev: false - /react-remove-scroll@2.6.3(@types/react@19.0.9)(react@19.0.0): + /react-remove-scroll@2.6.3(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} engines: {node: '>=10'} peerDependencies: @@ -1786,16 +1846,16 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.9)(react@19.0.0) - react-style-singleton: 2.2.3(@types/react@19.0.9)(react@19.0.0) + react-remove-scroll-bar: 2.3.8(@types/react@19.0.10)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.0.9)(react@19.0.0) - use-sidecar: 1.1.3(@types/react@19.0.9)(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.0.10)(react@19.0.0) + use-sidecar: 1.1.3(@types/react@19.0.10)(react@19.0.0) dev: false - /react-style-singleton@2.2.3(@types/react@19.0.9)(react@19.0.0): + /react-style-singleton@2.2.3(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} peerDependencies: @@ -1805,13 +1865,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 get-nonce: 1.0.1 react: 19.0.0 tslib: 2.8.1 dev: false - /react-textarea-autosize@8.5.6(@types/react@19.0.9)(react@19.0.0): + /react-textarea-autosize@8.5.6(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-aT3ioKXMa8f6zHYGebhbdMD2L00tKeRX1zuVuDx9YQK/JLLRSaSxq3ugECEmUB9z2kvk6bFSIoRHLkkUv0RJiw==} engines: {node: '>=10'} peerDependencies: @@ -1819,8 +1879,8 @@ packages: dependencies: '@babel/runtime': 7.26.9 react: 19.0.0 - use-composed-ref: 1.4.0(@types/react@19.0.9)(react@19.0.0) - use-latest: 1.3.0(@types/react@19.0.9)(react@19.0.0) + use-composed-ref: 1.4.0(@types/react@19.0.10)(react@19.0.0) + use-latest: 1.3.0(@types/react@19.0.10)(react@19.0.0) transitivePeerDependencies: - '@types/react' dev: false @@ -1851,24 +1911,12 @@ packages: reselect: 4.1.8 dev: false - /redux-thunk@3.1.0(redux@5.0.1): - resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} - peerDependencies: - redux: ^5.0.0 - dependencies: - redux: 5.0.1 - dev: false - /redux@4.2.1: resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} dependencies: '@babel/runtime': 7.26.9 dev: false - /redux@5.0.1: - resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - dev: false - /reflect-metadata@0.1.13: resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} dev: true @@ -1885,10 +1933,6 @@ packages: resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==} dev: false - /reselect@5.1.1: - resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} - dev: false - /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -1928,7 +1972,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -1944,7 +1987,6 @@ packages: hasBin: true requiresBuild: true dev: false - optional: true /set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -2154,8 +2196,8 @@ packages: engines: {node: '>=10'} dev: true - /type-fest@4.34.1: - resolution: {integrity: sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==} + /type-fest@4.35.0: + resolution: {integrity: sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A==} engines: {node: '>=16'} dev: false @@ -2181,7 +2223,7 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /use-callback-ref@1.3.3(@types/react@19.0.9)(react@19.0.0): + /use-callback-ref@1.3.3(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} peerDependencies: @@ -2191,12 +2233,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 tslib: 2.8.1 dev: false - /use-composed-ref@1.4.0(@types/react@19.0.9)(react@19.0.0): + /use-composed-ref@1.4.0(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==} peerDependencies: '@types/react': '*' @@ -2205,11 +2247,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 dev: false - /use-isomorphic-layout-effect@1.2.0(@types/react@19.0.9)(react@19.0.0): + /use-isomorphic-layout-effect@1.2.0(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==} peerDependencies: '@types/react': '*' @@ -2218,11 +2260,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 dev: false - /use-latest@1.3.0(@types/react@19.0.9)(react@19.0.0): + /use-latest@1.3.0(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==} peerDependencies: '@types/react': '*' @@ -2231,12 +2273,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 react: 19.0.0 - use-isomorphic-layout-effect: 1.2.0(@types/react@19.0.9)(react@19.0.0) + use-isomorphic-layout-effect: 1.2.0(@types/react@19.0.10)(react@19.0.0) dev: false - /use-sidecar@1.1.3(@types/react@19.0.9)(react@19.0.0): + /use-sidecar@1.1.3(@types/react@19.0.10)(react@19.0.0): resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: @@ -2246,7 +2288,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.0.9 + '@types/react': 19.0.10 detect-node-es: 1.1.0 react: 19.0.0 tslib: 2.8.1 diff --git a/proto b/proto index 11644ad..b7ea2e6 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 11644adc889ee8f0e0e90c11ccf386a081ee000f +Subproject commit b7ea2e6cc71f7393f9afe722204c5c33b6a6f2b6 diff --git a/src/_pages/login/api.ts b/src/_pages/login/api.ts deleted file mode 100644 index e89b722..0000000 --- a/src/_pages/login/api.ts +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import {AxiosRequestConfig, AxiosResponse} from "axios"; -import {userApi} from "../../../configutation"; - -const Login = async (username: string, password: string): Promise> => { - const options: AxiosRequestConfig = { - withCredentials: true - } - - return await userApi.userServiceLogin({ - username: username, - password: password - }, options); -} - -export {Login}; diff --git a/src/_pages/login/index.ts b/src/_pages/login/index.ts deleted file mode 100644 index cfabe5b..0000000 --- a/src/_pages/login/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {LoginPage} from "./ui"; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 30e5d35..b1cbf7a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -3,4 +3,4 @@ export const metadata = { description: '', }; -export {LoginPage as default} from "@/_pages/login" +export {LoginPage as default} from "@/plain-pages/login" diff --git a/src/app/users/[user_id]/page.tsx b/src/app/users/[user_id]/page.tsx index 2dae258..b8a00eb 100644 --- a/src/app/users/[user_id]/page.tsx +++ b/src/app/users/[user_id]/page.tsx @@ -1,35 +1 @@ -import React from 'react'; -import {AppShell, AppShellHeader, AppShellMain, Button, Group, Select, Stack, TextInput} from "@mantine/core"; -import {Header} from "@/components/header"; - -type PageProps = { - params: { - user_id: number - } -} - -const roles = [ - "Participant", "Moderator", "Admin" -] - -const Page = ({params}: PageProps) => { - return ( - - -
- - - - - - setUser({...user, role: roles.indexOf(event)})} + disabled={!props.canEdit} + /> + + + + + + ); +}; + +export {ClientPage}; diff --git a/src/plain-pages/users/index.tsx b/src/plain-pages/users/index.tsx new file mode 100644 index 0000000..4e27354 --- /dev/null +++ b/src/plain-pages/users/index.tsx @@ -0,0 +1 @@ +export * from "./page"; \ No newline at end of file diff --git a/src/plain-pages/users/page.tsx b/src/plain-pages/users/page.tsx new file mode 100644 index 0000000..6d3c192 --- /dev/null +++ b/src/plain-pages/users/page.tsx @@ -0,0 +1,29 @@ +"use server"; + +import {GetUsers} from "@/shared/api"; +import {ClientPage} from "./ui"; +import {Metadata} from "next"; + +const generateMetadata = async ({params}: Props): Promise => { + return { + title: 'Пользователи', + description: '', + }; +} + + +type Props = { + searchParams: Promise<{ page: number }> +} + +const Page = async (props: Props) => { + const page = (await props.searchParams).page || 1; + + const users = await GetUsers(page, 10); + + return ( + + ) +} + +export {Page as UsersPage, generateMetadata}; \ No newline at end of file diff --git a/src/plain-pages/users/ui.tsx b/src/plain-pages/users/ui.tsx new file mode 100644 index 0000000..3eaf65b --- /dev/null +++ b/src/plain-pages/users/ui.tsx @@ -0,0 +1,108 @@ +"use client"; + +import { + ActionIcon, + AppShell, + AppShellAside, + AppShellHeader, + AppShellMain, + Pagination, + Stack, + Table, + TableTbody, + TableTd, + TableTh, + TableThead, + TableTr, + TextInput, + Title +} from "@mantine/core"; +import Link from "next/link"; +import {IconPencil} from "@tabler/icons-react"; +import {Header} from "@/components/header"; +import React from "react"; +import {User} from "../../../proto/user/v1/api"; + + +type Props = { + users: User[], + page: number + max_page: number +}; + +const roles = [ + "Студент", + "Преподаватель", + "Администратор", +]; + + +const ClientPage = (props: Props) => { + const rows = props.users.map((user) => ( + + {user.username} + {/*{user.email}*/} + {roles[user.role]} + { + + } + + + )); + + return ( + + +
+ + + + Пользователи + + + + Никнейм + {/*Почта*/} + Роль + + + + {rows} +
+ ({ + component: Link, + href: `/users?page=${page}`, + })} + getControlProps={(control) => { + if (control === 'next') { + if (props.page === props.max_page) { + return {component: Link, href: `/users?page=${props.page}`}; + } + + return {component: Link, href: `/users?page=${+props.page + 1}`}; + } + + if (control === 'previous') { + if (props.page === 1) { + return {component: Link, href: `/users?page=${props.page}`}; + } + return {component: Link, href: `/users?page=${+props.page - 1}`}; + } + + return {}; + }} + /> +
+
+ + + + + + + ); +}; + +export {ClientPage}; \ No newline at end of file diff --git a/src/shared/api/config.ts b/src/shared/api/config.ts new file mode 100644 index 0000000..969f0ed --- /dev/null +++ b/src/shared/api/config.ts @@ -0,0 +1,9 @@ +import {Configuration, DefaultApi} from "../../../proto/user/v1/api"; + +const configuration = new Configuration({ + basePath: "http://localhost:60005", +}); + +const authApi = new DefaultApi(configuration); + +export {authApi}; \ No newline at end of file diff --git a/src/shared/api/index.ts b/src/shared/api/index.ts new file mode 100644 index 0000000..0e03d36 --- /dev/null +++ b/src/shared/api/index.ts @@ -0,0 +1 @@ +export * from "./ms-auth"; \ No newline at end of file diff --git a/src/shared/api/ms-auth.ts b/src/shared/api/ms-auth.ts new file mode 100644 index 0000000..a5d0a05 --- /dev/null +++ b/src/shared/api/ms-auth.ts @@ -0,0 +1,197 @@ +"use server"; + +import {AxiosRequestConfig} from "axios"; +import {decode} from "jsonwebtoken"; +import {cookies} from "next/headers"; +import {authApi} from "./config"; + +type Credentials = { + username: string, + password: string +} + +const CookieName: any = "SESSIONID"; + +type Grant = { + action: "create" | "read" | "update" | "delete"; + resource: "another-user" | "me-user" | "list-user" | "own-session"; +} + +type JWT = { + session_id: string + user_id: number + role: number + exp: number + iat: number + nbf: number + permissions: Grant[] +} + +class JWTWithPermissions { + public session_id: string + public user_id: number + public role: number + public exp: number + public iat: number + public nbf: number + public permissions: Grant[] + + constructor(jwt: JWT) { + this.session_id = jwt.session_id; + this.user_id = jwt.user_id; + this.role = jwt.role; + this.exp = jwt.exp; + this.iat = jwt.iat; + this.nbf = jwt.nbf; + this.permissions = jwt.permissions; + } + + public hasPermission(grant: Grant): boolean { + return this.permissions.some((permission) => permission.action === grant.action && permission.resource === grant.resource); + } +} + + +export const ParseJWT = async () => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const token = session.value; + + return new JWTWithPermissions(decode(token) as JWT); +} + + +export const Login = async (credentials: Credentials) => { + const options: AxiosRequestConfig = { + headers: { + "Authorization": "Basic " + btoa(credentials.username + ":" + credentials.password) + } + } + + const response = await authApi.login(options) + + const token = response.headers["authorization"].split(" ")[1]; + const decoded = decode(token) as JWT; + + const cookieArgs: any = { + httpOnly: true, + expires: new Date(decoded["exp"] * 1000), + sameSite: 'strict', + }; + + const cookieStore = await cookies(); + + cookieStore.set(CookieName, token, cookieArgs); + + return response.data; +}; +export const GetUser = async (id: number) => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const options: AxiosRequestConfig = { + headers: { + 'Authorization': "Bearer " + session.value + } + }; + + const response = await authApi.getUser(id, options); + + return response.data; +}; + +export const UpdateUser = async (id: number, role?: any, username?: string) => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const options: AxiosRequestConfig = { + headers: { + 'Authorization': "Bearer " + session.value + } + }; + + const req = { + role: role, + username: username + } + + const response = await authApi.updateUser(id, req, options); + + return response.data; +}; + +export const Logout = async () => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const options: AxiosRequestConfig = { + headers: { + 'Authorization': "Bearer " + session.value + } + }; + + const response = await authApi.logout(options) + + return response.data; +}; + +export const GetMe = async () => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const options: AxiosRequestConfig = { + headers: { + 'Authorization': "Bearer " + session.value + } + }; + + const response = await authApi.getMe(options); + + return response.data; +}; + +export const GetUsers = async (page: number, pageSize: number) => { + const cookieStore = await cookies(); + + const session = cookieStore.get(CookieName); + + if (session === undefined) { + throw new Error("Session id not found"); + } + + const options: AxiosRequestConfig = { + headers: { + 'Authorization': "Bearer " + session.value + } + }; + + const response = await authApi.listUsers(page, pageSize, options); + + return response.data; +} \ No newline at end of file