Skip to content
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# CreatorSuite
CreatorSuite is designed to be a useful tool in Core Service to help content creator to distribute their content.
CreatorSuite is designed to be a useful tool in [Core Service](https://github.com/nextdotid/core_service_sharp) to help content creator to distribute their content.
Base on that, creators don't need any third-party to list and distribute their contents, instead, they have a self-hosted service to help them organize content asset so that they can 100% control their data by themselves.

## frontend
[frontend repo](https://github.com/NextDotID/creator_suite_fronted)

## Frontend
docker-compose.yml includes the frontend service, [the source code is here.](https://github.com/NextDotID/creator_suite_frontend)

## Quick Start
```shell
cp .env.example .env

docker-compose up

docker-compose up --build // if you have any changes
Expand Down
46 changes: 46 additions & 0 deletions controller/content_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package controller

import (
"github.com/gin-gonic/gin"
"github.com/nextdotid/creator_suite/model"
"golang.org/x/xerrors"
"net/http"
"strconv"
)

type ContentInfoRequest struct {
ContentID int64 `json:"content_id"`
}

type ContentInfoResponse struct {
Extension string `json:"extension"`
ManagedContract string `json:"managed_contract"`
ContentName string `json:"content_name"`
Description string `json:"description"`
CreatorAddress string `json:"creator_address"`
KeyID int64 `json:"key_id"`
CreatedTime string `json:"created_time"`
UpdateTime string `json:"update_time"`
}

func content_info(c *gin.Context) {
req := ContentInfoRequest{}

req.ContentID, _ = strconv.ParseInt(c.Query("content_id"), 10, 64)
content, err := model.FindContentByID(req.ContentID)
if err != nil {
errorResp(c, http.StatusInternalServerError, xerrors.Errorf("Error in DB: %w", err))
return
}

c.JSON(http.StatusOK, ContentInfoResponse{
Extension: content.FileExtension,
ManagedContract: content.ManagedContract,
CreatorAddress: content.CreatorAddress,
ContentName: content.ContentName,
Description: content.Description,
KeyID: content.KeyID,
CreatedTime: content.CreatedAt.String(),
UpdateTime: content.UpdatedAt.String(),
})
}
92 changes: 56 additions & 36 deletions controller/create_record.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
package controller

import (
"fmt"
"github.com/nextdotid/creator_suite/types"
"github.com/nextdotid/creator_suite/util"
"math/big"
"net/http"

"github.com/gin-gonic/gin"
"github.com/nextdotid/creator_suite/model"
"github.com/nextdotid/creator_suite/types"
"github.com/nextdotid/creator_suite/util/dare"
"github.com/nextdotid/creator_suite/util/encrypt"
"golang.org/x/xerrors"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
)

type CreateRecordRequest struct {
ManagedContract string `json:"managed_contract"`
Network types.Network `json:"network"`
PaymentTokenAddress string `json:"payment_token_address"`
PaymentTokenAmount string `json:"payment_token_amount"`
Password string `json:"password"`
ContentName string `json:"content_name"`
EncryptionType int8 `json:"encryption_type"`
FileExtension string `json:"file_extension"`
Description string `json:"description"`
ManagedContract string `json:"managed_contract"`
Network types.Network `json:"network"`
Password string `json:"password"`
EncryptionType int8 `json:"encryption_type"`
FileExtension string `json:"file_extension"`
Description string `json:"description"`
CreatorAddress string `json:"creator_address"`
}

type CreateRecordResponse struct {
Expand All @@ -30,15 +30,24 @@ type CreateRecordResponse struct {

func create_record(c *gin.Context) {
req := CreateRecordRequest{}
if err := c.BindJSON(&req); err != nil {
fmt.Println(req)
errorResp(c, http.StatusBadRequest, xerrors.Errorf("Param error", err))
return
}
req.Network = types.Network(c.PostForm("network"))
if !req.Network.IsValid() {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("Cannot support the network right now"))
return
}
req.ManagedContract = c.PostForm("managed_contract")
req.Password = c.PostForm("password")
et, _ := strconv.ParseInt(c.PostForm("encryption_type"), 10, 64)
req.EncryptionType = int8(et)
req.Description = c.PostForm("description")
req.CreatorAddress = c.PostForm("creator_address")

file, err := c.FormFile("file")
if err != nil {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("get file error", err))
return
}
fileExtension := strings.Trim(filepath.Ext(file.Filename), ".")

var keyID int64
if req.EncryptionType == model.ENCRYPTION_TYPE_AES {
Expand All @@ -53,28 +62,39 @@ func create_record(c *gin.Context) {
}
}

tokenAmount := util.ToWei(req.PaymentTokenAmount, 18)
if tokenAmount == big.NewInt(0) {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("token amount invalid"))
return
}

content, err := model.CreateRecord(req.ManagedContract, keyID, req.EncryptionType,
req.FileExtension, req.Network, req.ContentName, req.Description)
fileExtension, req.Network, file.Filename, req.Description, req.CreatorAddress)
if err != nil {
errorResp(c, http.StatusInternalServerError, xerrors.Errorf("Error in DB: %w", err))
return
}

//err = model.CreateAsset(content.ID, req.ManagedContract, req.PaymentTokenAddress, tokenAmount, req.Network)
//if err != nil {
// updateErr := content.UpdateToInvalidStatus(content.ID)
// if updateErr != nil {
// log.Errorf("update content record err:%v", updateErr)
// }
// errorResp(c, http.StatusInternalServerError, xerrors.Errorf("Create an asset in Contract error: %v", err))
// return
//}
filePath := "/storage/" + strconv.FormatInt(content.ID, 10) + "/" + file.Filename
if err = os.Mkdir("/storage/"+strconv.FormatInt(content.ID, 10), os.ModePerm); err != nil {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("fail to create new folder, err: %w", err))
return
}
if err = c.SaveUploadedFile(file, filePath); err != nil {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("fail to upload the file, err:%w", err))
return
}

// generate encrypted file
if req.EncryptionType == model.ENCRYPTION_TYPE_AES {
src, _ := os.Open(filePath)
dst, _ := os.Create(filePath + ".enc")
key, err := encrypt.DeriveKey([]byte(req.Password), src, dst)
if err != nil {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("fail to DeriveKey to encrypt", err))
return
}
cfg := dare.Config{Key: key}
_, err = encrypt.AesEncrypt(src, dst, cfg)
if err != nil {
errorResp(c, http.StatusBadRequest, xerrors.Errorf("fail to encrypt the file", err))
return
}
}

c.JSON(http.StatusOK, CreateRecordResponse{
ContentID: content.ID,
Expand Down
Loading