feat: add im tenant db routing and chapter seven flows

This commit is contained in:
richjohnrambo
2026-08-13 11:30:48 +08:00
parent 774a448c12
commit 31f82d9c41
19 changed files with 5261 additions and 47 deletions
+55 -7
View File
@@ -18,6 +18,7 @@ import (
"mime"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"time"
@@ -131,12 +132,6 @@ func largeFileServeHTTP(wrt http.ResponseWriter, req *http.Request) {
return
}
if req.Method == http.MethodHead {
wrt.WriteHeader(http.StatusOK)
logs.Info.Println("media serve: completed", req.Method, "uid=", uid)
return
}
fd, rsc, err := mh.Download(tenantID, req.URL.String())
if err != nil {
writeHttpResponse(decodeStoreError(err, "", now, nil), err)
@@ -145,7 +140,15 @@ func largeFileServeHTTP(wrt http.ResponseWriter, req *http.Request) {
defer rsc.Close()
if err = authorizeLargeFileDownload(tenantID, uid, req.URL.String(), fd); err != nil {
writeHttpResponse(decodeStoreError(err, "", now, nil), err)
return
}
wrt.Header().Set("Content-Type", fd.MimeType)
if fd.ETag != "" {
wrt.Header().Set("ETag", strconv.Quote(fd.ETag))
}
asAttachment, _ := strconv.ParseBool(req.URL.Query().Get("asatt"))
// Force download for html files as a security measure.
asAttachment = asAttachment ||
@@ -159,7 +162,7 @@ func largeFileServeHTTP(wrt http.ResponseWriter, req *http.Request) {
strings.HasPrefix(fd.MimeType, "multipart/") ||
strings.HasPrefix(fd.MimeType, "text/")
if asAttachment {
wrt.Header().Set("Content-Disposition", "attachment")
wrt.Header().Set("Content-Disposition", contentDispositionAttachment(fd))
}
http.ServeContent(wrt, req, "", fd.UpdatedAt, rsc)
@@ -415,6 +418,11 @@ func (*grpcNodeServer) LargeFileServe(req *pbx.FileDownReq, stream pbx.Node_Larg
defer rsc.Close()
if err = authorizeLargeFileDownload(tenantID, uid, req.GetUri(), fd); err != nil {
writeResponse(decodeStoreError(err, msgID, now, nil), err)
return nil
}
resp.Code = http.StatusOK
resp.Text = http.StatusText(http.StatusOK)
resp.Meta.Name = fd.Location
@@ -445,6 +453,46 @@ func (*grpcNodeServer) LargeFileServe(req *pbx.FileDownReq, stream pbx.Node_Larg
return err
}
func authorizeLargeFileDownload(tenantID types.TenantID, uid types.Uid, rawURL string, fd *types.FileDef) error {
if fd == nil {
return types.ErrNotFound
}
fid := fd.Uid()
if fid.IsZero() && rawURL != "" && store.Store != nil {
fid = store.Store.GetMediaHandler().GetIdFromUrl(rawURL)
}
if fid.IsZero() || fd.TenantID != tenantID || fd.Status != types.UploadCompleted {
return types.ErrNotFound
}
allowed, err := store.Files.UserHasAccess(tenantID, fid.String(), uid)
if err != nil {
return err
}
if !allowed {
return types.ErrPermissionDenied
}
return nil
}
func contentDispositionAttachment(fd *types.FileDef) string {
name := strings.TrimSpace(filepath.Base(fd.Location))
if name == "." || name == "/" || name == string(filepath.Separator) {
name = fd.Uid().String()
}
clean := strings.Map(func(r rune) rune {
switch {
case r < 32 || r == 127 || r == '"' || r == '\\' || r == '/' || r == ':':
return -1
default:
return r
}
}, name)
if clean == "" {
clean = fd.Uid().String()
}
return mime.FormatMediaType("attachment", map[string]string{"filename": clean})
}
// LargeFileReceive is the gRPC equivalent of LargeFileReceiveHTTP.
func (*grpcNodeServer) LargeFileReceive(stream pbx.Node_LargeFileReceiveServer) error {
now := types.TimeNow()