파일 업로드 추가 / 화이트리스트에 권한 종류 추가

This commit is contained in:
2023-05-28 22:13:10 +09:00
parent 594b9fb700
commit 4347909aab
6 changed files with 427 additions and 88 deletions

View File

@ -1,13 +1,19 @@
package core
import (
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"net/http"
"os"
"path"
"sort"
"strconv"
"strings"
"sync/atomic"
"time"
@ -21,6 +27,54 @@ import (
"go.mongodb.org/mongo-driver/mongo/options"
)
type fileDocumentDesc struct {
Service string
Key string
Src string
Link string
Desc string
Extract bool
Timestamp int64
Contents []byte `json:",omitempty"`
}
func (fd *fileDocumentDesc) save() error {
// 새 파일 올라옴
if len(fd.Contents) == 0 {
return nil
}
var destFile string
if fd.Extract {
os.MkdirAll(fd.Link, os.ModePerm)
destFile = path.Join(fd.Link, fd.Src)
} else {
os.MkdirAll(path.Dir(fd.Link), os.ModePerm)
destFile = fd.Link
}
f, err := os.Create(destFile)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, bytes.NewBuffer(fd.Contents))
if err != nil {
return err
}
if fd.Extract {
switch path.Ext(destFile) {
case ".zip":
err = common.Unzip(destFile)
case ".tar":
err = common.Untar(destFile)
}
}
return err
}
func (caller apiCaller) isGlobalAdmin() bool {
if *noauth {
return true
@ -60,13 +114,18 @@ func (caller apiCaller) writeAccessableServices(w http.ResponseWriter) {
func (caller apiCaller) getAccessableServices() ([]*serviceDescription, []string) {
allservices := caller.mg.services.all()
v, ok := caller.userinfo["email"]
if !ok {
return nil, nil
}
email := v.(string)
_, admin := caller.admins[email]
admin := caller.isGlobalAdmin()
var email string
if !*noauth {
v, ok := caller.userinfo["email"]
if !ok {
return nil, nil
}
email := v.(string)
_, admin = caller.admins[email]
}
var output []*serviceDescription
var editable []string
@ -114,30 +173,79 @@ func (caller apiCaller) isValidUser(service any, category string) (valid bool, a
return svcdesc.isValidAPIUser(category, email), false
}
func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error {
serviceid := r.FormValue("service")
if len(serviceid) == 0 {
serviceid = "000000000000"
}
var files []fileDocumentDesc
err := caller.mg.mongoClient.FindAllAs(CollectionFile, bson.M{
"service": serviceid,
}, &files, options.Find().SetProjection(bson.M{
"contents": 0,
}))
if err != nil {
return err
}
enc := json.NewEncoder(w)
return enc.Encode(files)
}
var seq = uint32(0)
func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error {
// file, header, err := r.FormFile("file")
// if err != nil {
// logger.Error(err)
// w.WriteHeader(http.StatusBadRequest)
// return
// }
// defer file.Close()
serviceid := r.FormValue("service")
if len(serviceid) == 0 {
serviceid = "000000000000"
}
// contents, err := io.ReadAll(file)
// if err != nil {
// logger.Error(err)
// w.WriteHeader(http.StatusInternalServerError)
// return
// }
infile, header, err := r.FormFile("file")
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return err
}
defer infile.Close()
// ext := path.Ext(header.Filename)
// if ext == ".zip" {
desc := r.FormValue("desc")
contents, _ := io.ReadAll(infile)
extractstr := r.FormValue("extract")
extract, _ := strconv.ParseBool(extractstr)
// }
var b [5]byte
binary.BigEndian.PutUint32(b[0:4], uint32(time.Now().Unix()))
b[4] = byte(atomic.AddUint32(&seq, 1) % 255)
rf := hex.EncodeToString(b[:])
// // deploys 폴더는 파일시스템 서비스이므로 다운로드 가능
// filename := path.Join("deploys", name, version, name+ext)
return nil
var link string
if extract {
link = path.Join("static", serviceid, rf)
} else {
link = path.Join("static", serviceid, rf, header.Filename)
}
newdoc := fileDocumentDesc{
Contents: contents,
Src: header.Filename,
Timestamp: time.Now().UTC().Unix(),
Extract: extract,
Link: link,
Desc: desc,
Key: rf,
Service: serviceid,
}
_, _, err = caller.mg.mongoClient.UpsertOne(CollectionFile, bson.M{
"service": serviceid,
"key": rf,
}, newdoc)
if err == nil {
newdoc.Contents = nil
enc := json.NewEncoder(w)
enc.Encode(newdoc)
}
return err
}
func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) error {
@ -215,25 +323,6 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
return nil
}
// func (caller apiCaller) divisionAPI(w http.ResponseWriter, r *http.Request, svcid string, divid string) error {
// if r.Method == "PUT" {
// // svcid, divid에 statemeta 설정
// file, header, err := r.FormFile("file")
// if err != nil {
// logger.Error(err)
// w.WriteHeader(http.StatusBadRequest)
// return
// }
// defer file.Close()
// if header.
// stateFile, header, err := r.FormFile("file")
// if err != nil {
// return err
// }
// }
// }
func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
queryvals := r.URL.Query()
@ -277,6 +366,10 @@ func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error
}
filter := bson.M{"_id": service.Id}
if len(service.ServiceCode) == 0 {
service.ServiceCode = hex.EncodeToString(service.Id[6:])
}
success, _, err := mg.mongoClient.Update(CollectionService, filter, bson.M{
"$set": &service,
}, options.Update().SetUpsert(true))
@ -511,6 +604,8 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
err = caller.accountAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/upload") {
err = caller.uploadAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/files") {
err = caller.filesAPI(w, r)
}
if err != nil {