An open API service indexing awesome lists of open source software.

https://github.com/bluewave-labs/datahall

The open source DocSend alternative
https://github.com/bluewave-labs/datahall

datahall docsend document document-management file-management file-manager file-share file-sharing file-upload secure-storage

Last synced: 5 months ago
JSON representation

The open source DocSend alternative

Awesome Lists containing this project

README

          

![image](https://github.com/user-attachments/assets/b49700aa-1457-47c8-b8da-4193db776014)

Datahall

An open source DocSend alternative

Datahall is an open source DocSend alternative where you can share your files privately with anyone outside of your organization.

Currently, Datahall is in development. The current designs and the style guide can be viewed [here](https://www.figma.com/design/GLFfhwOQeHmbcflgCTuMKA/File-Server?node-id=0-1&t=be2sQyhaO4ylDg6z-1).

![Github social](https://github.com/user-attachments/assets/061eaa7d-0d56-4a32-8553-bbfb7fd9e0e3)

## Features & roadmap

* Uploading and editing files
* Sharing and link control
* Tracking and analytics
* Document viewer
* Company branding

## Tech stack

* [ReactJs](https://react.dev/)
* [MUI (React framework)](https://mui.com/)
* [Next.js](https://nextjs.org/)
* [Node.js](https://nodejs.org/en)
* [MongoDB](https://mongodb.com)

## Database

##### Data Types

User

| **Name** | **Type** | **Notes** |
| -------------- | --------- | ----------------------------------------------------------- |
| `userId` | `string` | **Primary Key**. Unique ID for each user |
| `firstName` | `string` | First name |
| `lastName` | `string` | Last name |
| `email` | `string` | **Unique**. User's email |
| `profilePicUrl`| `string` | URL to User's picture |
| `isActive` | `boolean` | Default: `true` |
| `isVerified` | `boolean` | Default: `false` |
| `lastLogin` | `Date` | Timestamp of the last login |
| `createdAt` | `Date` | **Not Null**. Timestamp when the user was created |
| `updatedAt` | `Date` | **Not Null**. Timestamp when the user was last updated |

Documents

| **Name** | **Type** | **Notes** |
| ----------------- | --------- | ----------------------------------------------------------- |
| `fileId` | `string` | **Primary Key**. Unique ID identifying the file |
| `parentFileId` | `string` | **Foreign Key**. References `Documents.fileId` |
| `fileName` | `string` | Name of the file |
| `type` | `string` | File type / extension |
| `fileDirectory` | `string` | Directory where the file is located |
| `fileSize` | `int` | Size of the file in bytes |
| `mimeType` | `string` | MIME type of the file |
| `createdBy` | `string` | **Foreign Key**. References `User.userId` |
| `createdAt` | `Date` | **Not Null**. Creation time |
| `updatedAt` | `Date` | **Not Null**. Last update time |
| `updatedBy` | `string` | **Foreign Key**. References `User.userId` |
| `totalViews` | `int` | Total number of times the file was viewed |
| `uniqueViews` | `int` | Number of unique viewers of the file |

Links

| **Name** | **Type** | **Notes** |
| ----------------- | --------- | ------------------------------------------------------------------- |
| `linkId` | `string` | **Primary Key**. Unique ID for the link |
| `fileId` | `string` | **Foreign Key**. References `Documents.fileId` |
| `linkName` | `string` | Name of the link |
| `linkUrl` | `string` | URL of the link |
| `isPublic` | `boolean` | Indicates if the link is public |
| `emailRequired` | `boolean` | Indicates if an email is required for download |
| `passwordRequired`| `boolean` | Indicates if a password is required to view and download the file |
| `linkPassword` | `string` | Password reqired to view and download the file |
| `linkUrl` | `string` | URL of the link |
| `canExpire` | `boolean` | Indicates if the link can expire |
| `expirationTime` | `Date` | Expiration date of the link (nullable) |
| `updatedAt` | `Date` | **Not Null**. Last update time |
| `createdAt` | `Date` | **Not Null**. Creation time |
| `createdBy` | `string` | **Foreign Key**. References `User.userId` |

Datahall

| **Name** | **Type** | **Notes** |
| ----------------- | --------- | ----------------------------------------------------------- |
| `folderId` | `string` | **Primary Key**. Unique ID for the folder |
| `folderName` | `string` | Name of the folder |
| `folderLocation` | `string` | Location of the folder |
| `updatedAt` | `Date` | **Not Null**. Last update time |
| `updatedBy` | `string` | **Foreign Key**. References `User.userId` |
| `createdAt` | `Date` | **Not Null**. Creation time |
| `createdBy` | `string` | **Foreign Key**. References `User.userId` |

AccessLogs

| **Name** | **Type** | **Notes** |
| ----------------- | --------- | ----------------------------------------------------------- |
| `logId` | `string` | **Primary Key**. Unique ID for each access log |
| `linkId` | `string` | **Foreign Key**. ID of the link accessed |
| `userId` | `string` | **Foreign Key**. ID of the user who accessed the link |
| `accessTime` | `Date` | **Not Null**. Timestamp when the link was accessed |
| `ipAddress` | `string` | IP address of the user who accessed the link |

## Endpoints

### Auth

GET /api/v1/auth/users

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

###### Response Payload

> | Type | Notes |
> | ------------- | ------------------------------------- |
> | `Array` | Returns an array containing all users |

POST /api/v1/auth/register

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | multipart/form-data |

##### Form

> | Name | Type | Notes |
> | --------- | --------------- | ----------------------------------------------- |
> | firstName | `string` | |
> | lastName | `string` | |
> | email | `string` | Valid email address |
> | password | `string` | Min 8 chars, One Upper, one number, one special |
> | role | `Array` | Array of user roles |

##### Response Payload

> | Type | Notes |
> | ---- | -------------- |
> | User | User data |
> | JWT | JSON web token |

POST /api/v1/auth/login

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | POST |
> | content-type | application/json |

##### Body

> | Name | Type | Notes |
> | -------- | -------- | ------------------- |
> | email | `string` | Valid email address |
> | password | `string` | |

##### Response Payload

> | Type | Notes |
> | ---- | -------------- |
> | User | User data |
> | JWT | JSON web token |

POST /api/v1/auth/user/{userId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | multipart/form-data |

##### Form

> | Name | Type | Notes |
> | ----------- | -------- | --------------------------- |
> | firstName | `string` | Optional |
> | lastName | `string` | Optional |
> | profileIame | `file` | Optional |
> | password | `string` | Required to change password |
> | newPassword | `string` | Required to change password |

###### Response Payload

> | Type | Notes |
> | ------ | ------------------------ |
> | `User` | Returns the updated user |

POST /api/v1/auth/recovery/request

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | POST |
> | content-type | application/json |

##### Body

> | Name | Type | Notes |
> | ----- | -------- | ------------ |
> | email | `string` | User's email |

###### Response Payload

> | Type | Notes |
> | --------------- | --------------------------------------- |
> | `RecoveryToken` | Returns a recovery token if email found |

POST /api/v1/auth/recovery/validate

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | POST |
> | content-type | application/json |

##### Body

> | Name | Type | Notes |
> | ------------- | -------- | ----------------------------------- |
> | recoveryToken | `string` | Token issued in `/recovery/request` |

###### Response Payload

> | Type | Notes |
> | --------------- | -------------------------- |
> | `RecoveryToken` | Returns the recovery token |

POST /api/v1/auth/recovery/reset

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | POST |
> | content-type | application/json |

##### Body

> | Name | Type | Notes |
> | ------------- | -------- | --------------------------------------------- |
> | recoveryToken | `string` | Token issued returned by `/recovery/validate` |
> | password | `string` | User's new password` |

###### Response Payload

> | Type | Notes |
> | ------ | ------------------------ |
> | `User` | Returns the updated user |

---

### Documents

GET /api/v1/documents

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ----------------------------------------- |
> | `Array` | Array of all latest versions of documents |

GET /api/v1/documents/versions/{documentId}

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ------------------------------------------------------- |
> | `Array` | Array of all documents versions for the parent document |

GET /api/v1/document/{documentId}

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ------------------------------------------------------------------- |
> | `Document` | Document with the id in the request parameter |

POST /api/v1/document

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | multipart/form-data |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | -------------------------------------- | --------------------------------------- |
> | `fileData` | `string` | The file to be uploaded | |
> | `fileName` | `string` | Name of the file | |
> | `type` | `string` | File type / extension | |
> | `fileDirectory` | `string` | Directory where the file should go | |
> | `fileSize` | `int` | Size of the file in bytes | |
> | `mimeType` | `string` | MIME type of the file | |
> | `userId` | `string` | UserId of current user | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `Document` | Returns newly created `Document` |

POST /api/v1/document/delete/{fileId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `None` | No payload returned |

POST /api/v1/document/edit/{fileId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | multipart/form-data |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | -------------------------------------- | --------------------------------------- |
> | `fileData` | `string` | The file to be uploaded | |
> | `fileName` | `string` | Name of the file | |
> | `type` | `string` | File type / extension | |
> | `fileDirectory` | `string` | Directory where the file should go | |
> | `fileSize` | `int` | Size of the file in bytes | |
> | `mimeType` | `string` | MIME type of the file | |
> | `userId` | `string` | UserId of current user | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `Document` | Returns updated `Document` |

### DataRooms

GET /api/v1/datarooms

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ---------------------- |
> | `Array` | Array of all datarooms |

GET /api/v1/dataroom/{folderId}

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ---------------------------------------------------- |
> | `DataRoom` | Single dataroom with the id in the request parameter |

POST /api/v1/dataroom

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | --------------------------- | --------------------------------------- |
> | `folderName` | `string` | Name of the file | |
> | `folderLocation` | `string` | File type / extension | |
> | `userId` | `string` | UserId of current user | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `DataRoom` | Returns newly created `DataRoom` |

POST /api/v1/dataroom/delete/{folderId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `None` | No payload returned |

POST /api/v1/dataroom/edit/{folderId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | --------------------------- | --------------------------------------- |
> | `folderName` | `string` | Name of the file | |
> | `folderLocation` | `string` | File type / extension | |
> | `userId` | `string` | UserId of current user | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `DataRoom` | Returns updated `DataRoom` |

### Links

GET /api/v1/links

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ---------------------- |
> | `Array` | Array of all links |

GET /api/v1/link/{linkId}

##### Method/Headers

> | Method/Headers | Value |
> | -------------- | ---------------- |
> | Method | GET |
> | content-type | application/json |

##### Response Payload

> | Type | Notes |
> | ------------------ | ---------------------------------------------------- |
> | `Link` | Singe Link with the id in the request parameter |

POST /api/v1/link

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | ------------------------------------------------ | --------------------------------------- |
> | `fileId` | `string` | The fileId of the file the link is generated for | |
> | `linkName` | `string` | Name of the link | |
> | `isPublic` | `boolean` | Indicates if the link is public | |
> | `emailRequired` | `boolean` | Indicates if email is required to download | |
> | `passwordRequired`| `boolean` | Indicates if password is required to download | |
> | `linkPassword` | `string` | Password required to download | |
> | `canExpire` | `boolean` | Indicates if the link can expire | |
> | `expirationTime` | `Date` | Date in which the link expires | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `Link` | Returns newly created `Link` |

POST /api/v1/link/delete/{linkId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `None` | No payload returned |

POST /api/v1/link/edit/{linkId}

###### Method/Headers

> | Method/Headers | Value |
> | -------------- | ------------------- |
> | Method | POST |
> | content-type | application/json |

##### Body
> | Name | Type | Notes | Accepted Values |
> | ----------------- | --------- | ------------------------------------------------ | --------------------------------------- |
> | `linkName` | `string` | Name of the link | |
> | `isPublic` | `boolean` | Indicates if the link is public | |
> | `emailRequired` | `boolean` | Indicates if email is required to download | |
> | `passwordRequired`| `boolean` | Indicates if password is required to download | |
> | `linkPassword` | `string` | Password required to download | |
> | `canExpire` | `boolean` | Indicates if the link can expire | |
> | `expirationTime` | `Date` | Date in which the link expires | |

###### Response Payload

> | Type | Notes |
> | --------- | --------------------------------- |
> | `Link` | Returns updated `Link` |