Merge pull request #8 from Nekiiinkognito/improvement/ABACImplementation
Improvement/abac implementation
This commit is contained in:
commit
c816a4612c
4
.gitignore
vendored
4
.gitignore
vendored
@ -13,6 +13,10 @@ dist-ssr
|
||||
*.local
|
||||
secret.env
|
||||
|
||||
privkey.pem
|
||||
fullchain.pem
|
||||
gin.log
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
|
||||
25
compose.yml
Normal file
25
compose.yml
Normal file
@ -0,0 +1,25 @@
|
||||
services:
|
||||
|
||||
nginx:
|
||||
build: ./enshi
|
||||
ports:
|
||||
- 127.0.0.1:80:80
|
||||
- 127.0.0.1:443:443
|
||||
networks:
|
||||
- app-network
|
||||
restart: unless-stopped
|
||||
|
||||
enshi_back:
|
||||
build: ./enshi_back
|
||||
ports:
|
||||
- 127.0.0.1:9876:9876
|
||||
networks:
|
||||
- app-network
|
||||
environment:
|
||||
- ENV=docker
|
||||
- DOMAIN=localhost
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
1
enshi/.dockerignore
Normal file
1
enshi/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
||||
22
enshi/Dockerfile
Normal file
22
enshi/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
||||
FROM node:18-alpine as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV VITE_ENV=docker
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Certificates
|
||||
COPY ./nginx/fullchain.pem /etc/nginx/ssl/
|
||||
COPY ./nginx/privkey.pem /etc/nginx/ssl/
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
@ -1,50 +1 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
```js
|
||||
export default tseslint.config({
|
||||
languageOptions: {
|
||||
// other options...
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
||||
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import react from 'eslint-plugin-react'
|
||||
|
||||
export default tseslint.config({
|
||||
// Set the react version
|
||||
settings: { react: { version: '18.3' } },
|
||||
plugins: {
|
||||
// Add the react plugin
|
||||
react,
|
||||
},
|
||||
rules: {
|
||||
// other rules...
|
||||
// Enable its recommended rules
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
},
|
||||
})
|
||||
```
|
||||
# README
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ['dist'] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
},
|
||||
plugins: {
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
37
enshi/nginx/nginx.conf
Normal file
37
enshi/nginx/nginx.conf
Normal file
@ -0,0 +1,37 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
# server_name nekiiinkognito.ru www.nekiiinkognito.ru;
|
||||
server_name localhost;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
||||
ssl_ecdh_curve secp384r1;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_tickets off;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api/v1/ {
|
||||
proxy_pass http://enshi_back:9876/;
|
||||
}
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
}
|
||||
23
enshi/package-lock.json
generated
23
enshi/package-lock.json
generated
@ -24,6 +24,7 @@
|
||||
"i18next": "^23.14.0",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"immer": "^10.1.1",
|
||||
"interweave": "^13.1.0",
|
||||
"jotai": "^2.9.3",
|
||||
"jotai-immer": "^0.4.1",
|
||||
"primereact": "^10.8.2",
|
||||
@ -4425,6 +4426,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
@ -5321,6 +5328,22 @@
|
||||
"integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/interweave": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/interweave/-/interweave-13.1.0.tgz",
|
||||
"integrity": "sha512-JIDq0+2NYg0cgL7AB26fBcV0yZdiJvPDBp+aF6k8gq6Cr1kH5Gd2/Xqn7j8z+TGb8jCWZn739jzalCz+nPYwcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escape-html": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "ko-fi",
|
||||
"url": "https://ko-fi.com/milesjohnson"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "enshi",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint-build": "tsc -b && vite build",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
@ -26,6 +27,7 @@
|
||||
"i18next": "^23.14.0",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"immer": "^10.1.1",
|
||||
"interweave": "^13.1.0",
|
||||
"jotai": "^2.9.3",
|
||||
"jotai-immer": "^0.4.1",
|
||||
"primereact": "^10.8.2",
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import axios from "axios";
|
||||
|
||||
const environment = import.meta.env.VITE_ENV || 'development';
|
||||
// const environment = "docker"
|
||||
const baseURL = environment === "docker" ? "https://localhost/api/v1/" : "http://127.0.0.1:9876/";
|
||||
|
||||
export const axiosLocalhost = axios.create(
|
||||
{
|
||||
baseURL: `http://127.0.0.1:9876/`,
|
||||
baseURL: baseURL,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
|
||||
@ -1,8 +1,32 @@
|
||||
package global
|
||||
|
||||
const PathForCookies = "/"
|
||||
const DomainForCookies = "127.0.0.1"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var PathForCookies = "/"
|
||||
var DomainForCookies = "127.0.0.1"
|
||||
|
||||
const SecureForCookies = false
|
||||
const HttpOnlyForCookies = false
|
||||
|
||||
const GinWorkPath = "localhost:9876"
|
||||
// Change to 0.0.0.0 when docker this
|
||||
const GinWorkPath = "127.0.0.1:9876"
|
||||
|
||||
func GetGinWorkPath() string {
|
||||
|
||||
if os.Getenv("DOMAIN") != "" {
|
||||
DomainForCookies = os.Getenv("DOMAIN")
|
||||
PathForCookies = "/api/v1/"
|
||||
fmt.Println("DomainForCookies is", DomainForCookies)
|
||||
}
|
||||
|
||||
if os.Getenv("ENV") == "docker" {
|
||||
fmt.Println("GinWorkPath is docker 0.0.0.0:9876")
|
||||
return "0.0.0.0:9876"
|
||||
}
|
||||
|
||||
fmt.Println("GinWorkPath is local 127.0.0.1:9876")
|
||||
return GinWorkPath
|
||||
}
|
||||
|
||||
@ -8,6 +8,9 @@ import (
|
||||
"enshi/global"
|
||||
"enshi/routes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@ -27,12 +30,20 @@ func main() {
|
||||
defer db_connection.Dbx_connection.Close(context.Background())
|
||||
|
||||
router := gin.Default()
|
||||
|
||||
f, err := os.OpenFile("gin.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
gin.DefaultWriter = io.MultiWriter(f)
|
||||
|
||||
if err := routes.SetupRotes(router); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Transaction
|
||||
// Test Transaction
|
||||
tx, _ := db_connection.Dbx.Begin(context.Background())
|
||||
defer tx.Rollback(context.Background())
|
||||
|
||||
@ -48,7 +59,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
router.Run(global.GinWorkPath)
|
||||
router.Run(global.GetGinWorkPath())
|
||||
|
||||
fmt.Printf("Hey!, %v", "you")
|
||||
}
|
||||
|
||||
118
enshi_back/middleware/MiddlewareProvider.go
Normal file
118
enshi_back/middleware/MiddlewareProvider.go
Normal file
@ -0,0 +1,118 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"enshi/ABAC/rules"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type WorkRule struct {
|
||||
Rules []rules.RuleFunction
|
||||
MustBeCompleted int
|
||||
}
|
||||
|
||||
type Policy func(c *gin.Context) (bool, []error)
|
||||
type RuleSets map[string]rules.RuleFunction
|
||||
type RulesToCheck map[string]WorkRule
|
||||
|
||||
type MiddlewareProvider struct {
|
||||
Policies map[string]Policy
|
||||
}
|
||||
|
||||
func CreateRuleFunction(rulesToCheck []rules.RuleFunction, mustBeCompleted int) rules.RuleFunction {
|
||||
return func(c *gin.Context) (bool, []error) {
|
||||
|
||||
isAllowed, errors := rules.CheckRules(
|
||||
c,
|
||||
rulesToCheck,
|
||||
mustBeCompleted,
|
||||
)
|
||||
|
||||
return isAllowed, errors
|
||||
}
|
||||
}
|
||||
|
||||
func CreatePolicy(ruleSets RuleSets) Policy {
|
||||
|
||||
return func(c *gin.Context) (bool, []error) {
|
||||
targetAction, exists := c.Get("target")
|
||||
if !exists {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for action, rule := range ruleSets {
|
||||
if action == targetAction {
|
||||
return rules.CheckRule(c, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Accepts
|
||||
//
|
||||
// ruleSetName -> `string` name of the policy(like old one "postPolicy" etc.)
|
||||
//
|
||||
// rulesToCheck -> map where keys like ["GET", "POST", etc.] and values are struct of type {rules: [list of rules to check], mustBeCompleted: how many rules must be completed from the list before}
|
||||
func (m *MiddlewareProvider) RegisterPolicy(
|
||||
ruleSetName string,
|
||||
rulesToCheck RulesToCheck,
|
||||
) error {
|
||||
|
||||
for k := range m.Policies {
|
||||
if k == ruleSetName {
|
||||
return fmt.Errorf("name: " + ruleSetName + " already exists")
|
||||
}
|
||||
}
|
||||
|
||||
newRuleSets := make(RuleSets)
|
||||
for setName, workRule := range rulesToCheck {
|
||||
newRuleFunction := CreateRuleFunction(workRule.Rules, workRule.MustBeCompleted)
|
||||
newRuleSets[setName] = newRuleFunction
|
||||
}
|
||||
|
||||
newPolicy := CreatePolicy(newRuleSets)
|
||||
|
||||
m.Policies[ruleSetName] = newPolicy
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MiddlewareProvider) GetMiddleware(
|
||||
policyName string,
|
||||
) gin.HandlerFunc {
|
||||
|
||||
return func(c *gin.Context) {
|
||||
|
||||
validName := false
|
||||
for key := range m.Policies {
|
||||
if key == policyName {
|
||||
validName = true
|
||||
}
|
||||
}
|
||||
if !validName {
|
||||
c.Abort()
|
||||
fmt.Println("invalid policy name: " + policyName)
|
||||
return
|
||||
}
|
||||
|
||||
isAllowed, errors := m.Policies[policyName](c)
|
||||
|
||||
if rules.ShouldAbortRequest(c, isAllowed, errors) {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (m *MiddlewareProvider) InitMiddlewareProvider(policies map[string]RulesToCheck) {
|
||||
for middlewareName, rulesToCheck := range policies {
|
||||
m.RegisterPolicy(middlewareName, rulesToCheck)
|
||||
}
|
||||
}
|
||||
30
enshi_back/middleware/TargetMiddleware.go
Normal file
30
enshi_back/middleware/TargetMiddleware.go
Normal file
@ -0,0 +1,30 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
GET = "GET"
|
||||
PUT = "PUT"
|
||||
POST = "POST"
|
||||
DELETE = "DELETE"
|
||||
)
|
||||
|
||||
func TargetMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
switch c.Request.Method {
|
||||
case "DELETE":
|
||||
c.Set("target", DELETE)
|
||||
case "PUT":
|
||||
c.Set("target", PUT)
|
||||
case "POST":
|
||||
c.Set("target", POST)
|
||||
case "GET":
|
||||
c.Set("target", DELETE)
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
159
enshi_back/routes/middlewareSetup.go
Normal file
159
enshi_back/routes/middlewareSetup.go
Normal file
@ -0,0 +1,159 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
globalrules "enshi/ABAC/GlobalRules"
|
||||
"enshi/ABAC/rules"
|
||||
"enshi/middleware"
|
||||
)
|
||||
|
||||
const (
|
||||
POST_MIDDLEWARE = "POST_MIDDLEWARE"
|
||||
BLOG_MIDDLEWARE = "BLOG_MIDDLEWARE"
|
||||
PROFILE_MIDDLEWARE = "PROFILE_MIDDLEWARE"
|
||||
BOOKMARK_MIDDLEWARE = "BOOKMARK_MIDDLEWARE"
|
||||
POST_BLOG_MIDDLEWARE = "POST_BLOG_MIDDLEWARE"
|
||||
POST_VOTE_MIDDLEWARE = "POST_VOTE_MIDDLEWARE"
|
||||
POST_VOTES_MIDDLEWARE = "POST_VOTES_MIDDLEWARE"
|
||||
)
|
||||
|
||||
var MiddlewareProvider = middleware.MiddlewareProvider{
|
||||
Policies: make(map[string]middleware.Policy),
|
||||
}
|
||||
|
||||
var policiesToRegister = map[string]middleware.RulesToCheck{
|
||||
POST_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.POST: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.PUT: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfThePostRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfThePostRule,
|
||||
globalrules.IsAdminRule,
|
||||
},
|
||||
MustBeCompleted: 2,
|
||||
},
|
||||
},
|
||||
|
||||
BOOKMARK_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.POST: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
BLOG_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.POST: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.PUT: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfTheBlogRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfTheBlogRule,
|
||||
globalrules.IsAdminRule,
|
||||
},
|
||||
MustBeCompleted: 2,
|
||||
},
|
||||
},
|
||||
|
||||
POST_VOTE_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.POST: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
POST_VOTES_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
PROFILE_MIDDLEWARE: {
|
||||
middleware.PUT: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
POST_BLOG_MIDDLEWARE: {
|
||||
middleware.PUT: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfThePostRule,
|
||||
globalrules.IsOwnerOfTheBlogRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfThePostRule,
|
||||
globalrules.IsOwnerOfTheBlogRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func InitMiddlewareProvider() {
|
||||
MiddlewareProvider.InitMiddlewareProvider(policiesToRegister)
|
||||
}
|
||||
@ -43,7 +43,36 @@ func testAuth(c *gin.Context) {
|
||||
}
|
||||
|
||||
func SetupRotes(g *gin.Engine) error {
|
||||
InitMiddlewareProvider()
|
||||
|
||||
g.Use(middleware.CORSMiddleware())
|
||||
g.Use(middleware.TargetMiddleware())
|
||||
|
||||
testGroup := g.Group("/test/")
|
||||
testGroup.Use(MiddlewareProvider.GetMiddleware(POST_MIDDLEWARE))
|
||||
|
||||
testGroup.GET(
|
||||
"posts/:post-id",
|
||||
postsRoutes.GetPost,
|
||||
)
|
||||
|
||||
testGroup.GET(
|
||||
"posts/random",
|
||||
postsRoutes.GetRandomPost,
|
||||
)
|
||||
|
||||
testGroup.PUT(
|
||||
"posts/:post-id",
|
||||
postsRoutes.UpdatePost,
|
||||
)
|
||||
testGroup.POST(
|
||||
"posts",
|
||||
postsRoutes.CreatePost,
|
||||
)
|
||||
testGroup.DELETE(
|
||||
"posts/:post-id",
|
||||
postsRoutes.DeletePost,
|
||||
)
|
||||
|
||||
// Free group routes
|
||||
freeGroup := g.Group("/")
|
||||
|
||||
418
package-lock.json
generated
418
package-lock.json
generated
@ -1,418 +0,0 @@
|
||||
{
|
||||
"name": "Enshi",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@radix-ui/react-toast": "^1.2.2",
|
||||
"interweave": "^13.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/primitive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
|
||||
"integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-collection": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
|
||||
"integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0",
|
||||
"@radix-ui/react-context": "1.1.0",
|
||||
"@radix-ui/react-primitive": "2.0.0",
|
||||
"@radix-ui/react-slot": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
|
||||
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
|
||||
"integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
|
||||
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-dismissable-layer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz",
|
||||
"integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.0",
|
||||
"@radix-ui/react-compose-refs": "1.1.0",
|
||||
"@radix-ui/react-primitive": "2.0.0",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-icons": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz",
|
||||
"integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz",
|
||||
"integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.0.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
|
||||
"integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
|
||||
"integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-toast": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.2.tgz",
|
||||
"integrity": "sha512-Z6pqSzmAP/bFJoqMAston4eSNa+ud44NSZTiZUmUen+IOZ5nBY8kzuU5WDBVyFXPtcW6yUalOHsxM/BP6Sv8ww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.0",
|
||||
"@radix-ui/react-collection": "1.1.0",
|
||||
"@radix-ui/react-compose-refs": "1.1.0",
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.1",
|
||||
"@radix-ui/react-portal": "1.1.2",
|
||||
"@radix-ui/react-presence": "1.1.1",
|
||||
"@radix-ui/react-primitive": "2.0.0",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||
"@radix-ui/react-visually-hidden": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
||||
"integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-controllable-state": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
|
||||
"integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
|
||||
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
|
||||
"integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz",
|
||||
"integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/interweave": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/interweave/-/interweave-13.1.0.tgz",
|
||||
"integrity": "sha512-JIDq0+2NYg0cgL7AB26fBcV0yZdiJvPDBp+aF6k8gq6Cr1kH5Gd2/Xqn7j8z+TGb8jCWZn739jzalCz+nPYwcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escape-html": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "ko-fi",
|
||||
"url": "https://ko-fi.com/milesjohnson"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.23.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@radix-ui/react-toast": "^1.2.2",
|
||||
"interweave": "^13.1.0"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user