|
1 | | -# flexson |
| 1 | +<h2 align="center"> |
| 2 | + <div> |
| 3 | + <a style="color:5dc4f3" href="https://github.com/ambyte/flexson"> |
| 4 | + <img src="app/assets/logo.png" width="120" /> |
| 5 | + <br> |
| 6 | + Flexson |
| 7 | + </a> |
| 8 | + </div> |
| 9 | + <br> |
| 10 | + The Powerful JSON Data Management Platform |
| 11 | +</h2> |
| 12 | + |
| 13 | +<p align="center"> |
| 14 | +A comprehensive platform for efficient JSON file management with robust authentication, collaborative group workspaces, secure API access, and versatile data endpoints. Flexson streamlines creating, organizing, and sharing JSON data through an intuitive interface while maintaining enterprise-level security and access controls. |
| 15 | +</p> |
| 16 | + |
| 17 | +# Features |
| 18 | + |
| 19 | +- 📁 Create, view, edit, and delete JSON files |
| 20 | +- 🌐 Public and protected REST API for get and save files |
| 21 | +- 🔍 Organize files into groups |
| 22 | +- 🔄 Real-time JSON validation and formatting |
| 23 | +- 🔐 JWT authentication (register, login, token refresh) |
| 24 | +- 🔑 API key generation and management |
| 25 | +- 🛡️ Flexible group access (public write, protected by API key) |
| 26 | +- 🖥️ Modern UI with Vuetify |
| 27 | + |
| 28 | +# Quick Start |
| 29 | + |
| 30 | +### Local |
| 31 | + |
| 32 | +1. Clone the repository and install dependencies (`npm install` or `yarn install`) |
| 33 | +2. Start the development server: `npm run dev` |
| 34 | +3. The app will be available at http://localhost:3000 |
| 35 | + |
| 36 | +### Docker |
| 37 | + |
| 38 | +- Use `docker-compose up -d` to start in containers |
| 39 | +- For production: `docker build -t flexson .` and `docker run -d -p 80:80 --name flexson flexson` |
| 40 | + |
| 41 | +### Docker Hub |
| 42 | + |
| 43 | +``` |
| 44 | +services: |
| 45 | + flexson: |
| 46 | + image: ambyte/flexson:latest |
| 47 | + container_name: flexson-app |
| 48 | + restart: unless-stopped |
| 49 | + ports: |
| 50 | + - "8123:80" |
| 51 | + environment: |
| 52 | + - APP_JWT_SECRET=your_super_secure_jwt_secret_key_change_in_production |
| 53 | + - APP_MONGO_URI=mongodb://admin:password@mongo:27017 |
| 54 | + - APP_MONGO_DB=flexsondb |
| 55 | + - APP_ADMIN_USERNAME=admin |
| 56 | + - APP_ADMIN_PASSWORD=1password |
| 57 | + - APP_PUBLIC_DISABLE_REGISTRATION=true |
| 58 | + - APP_PUBLIC_BASE_URL=https://yourwebaddress.com |
| 59 | + depends_on: |
| 60 | + - mongo |
| 61 | + networks: |
| 62 | + - app-network |
| 63 | +
|
| 64 | + mongo: |
| 65 | + image: mongo:latest |
| 66 | + container_name: flexson-db |
| 67 | + restart: unless-stopped |
| 68 | + ports: |
| 69 | + - "27027:27017" |
| 70 | + environment: |
| 71 | + MONGO_INITDB_ROOT_USERNAME: admin |
| 72 | + MONGO_INITDB_ROOT_PASSWORD: password |
| 73 | + volumes: |
| 74 | + - mongodb_data:/data/db |
| 75 | + networks: |
| 76 | + - app-network |
| 77 | +
|
| 78 | +volumes: |
| 79 | + mongodb_data: |
| 80 | +
|
| 81 | +networks: |
| 82 | + app-network: |
| 83 | + driver: bridge |
| 84 | +
|
| 85 | +``` |
| 86 | + |
| 87 | +# Architecture |
| 88 | + |
| 89 | +### Frontend |
| 90 | + |
| 91 | +- **Nuxt 3** (Vue 3, TypeScript) |
| 92 | +- **Pinia** for state management |
| 93 | +- **Vuetify** UI components |
| 94 | +- **Components**: JSON editor, file forms, theme toggle, etc. |
| 95 | + |
| 96 | +### Backend |
| 97 | + |
| 98 | +- **Nuxt server routes** (TypeScript) |
| 99 | +- **MongoDB** for storing users, files, groups, API keys |
| 100 | +- **JWT** for authentication and authorization |
| 101 | +- **API keys** for protected group access |
| 102 | +- **Public API** for submitting data to groups with public write enabled |
| 103 | + |
| 104 | +# API |
| 105 | + |
| 106 | +If the group is labeled protected, then you must specify the x-api-key with the previously created API key in the request header. |
| 107 | + |
| 108 | +``` |
| 109 | +x-api-key: "your_api_key" |
| 110 | +``` |
| 111 | + |
| 112 | +### Public & Protected Group API |
| 113 | + |
| 114 | +- `GET /api/data/{userslug}/{groupslug}` — Get all files in a group (API key required if protected) |
| 115 | +- `GET /api/data/{userslug}/{groupslug}/{fileslug}` — Get a specific file from a group (API key required if protected) |
| 116 | +- `POST /api/data/{userslug}/{groupslug}` — Submit new JSON or update existing file in a group (if public write is enabled, API key required if protected) |
| 117 | + |
| 118 | +#### Example: Get all files in a group (protected) |
| 119 | + |
| 120 | +```js |
| 121 | +fetch("http://localhost:3000/api/data/someuser/team-reports", { |
| 122 | + headers: { "X-API-Key": "<your_api_key>" }, |
| 123 | +}) |
| 124 | + .then((res) => res.json()) |
| 125 | + .then(console.log); |
| 126 | +``` |
| 127 | + |
| 128 | +#### Example: Get a specific file from a group (protected) |
| 129 | + |
| 130 | +```js |
| 131 | +fetch("http://localhost:3000/api/data/someuser/team-reports/somefile", { |
| 132 | + headers: { "X-API-Key": "<your_api_key>" }, |
| 133 | +}) |
| 134 | + .then((res) => res.json()) |
| 135 | + .then(console.log); |
| 136 | +``` |
| 137 | + |
| 138 | +### Example: Public submission |
| 139 | + |
| 140 | +```js |
| 141 | +const data = { |
| 142 | + name: "Sample Report", |
| 143 | + slug: "sample-report" // optionally |
| 144 | + content: { title: "Weekly", items: [1, 2, 3] }, |
| 145 | + description: "Weekly report", // optionally |
| 146 | +}; |
| 147 | +fetch("http://localhost:3000/api/data/someuser/team-reports", { |
| 148 | + method: "POST", |
| 149 | + headers: { "Content-Type": "application/json" }, |
| 150 | + body: JSON.stringify(data), |
| 151 | +}) |
| 152 | + .then((res) => res.json()) |
| 153 | + .then(console.log); |
| 154 | +``` |
| 155 | + |
| 156 | +#### Submission JSON response |
| 157 | + |
| 158 | +```json |
| 159 | +{ |
| 160 | + "success": true, |
| 161 | + "message": "Data saved successfully", |
| 162 | + "fileUrl": "http://localhost:3000/api/data/someuser/team-reports/sample-report" |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +# License |
| 167 | + |
| 168 | +MIT License |
0 commit comments