Support meeting note upload registration
This commit is contained in:
+52
-1
@@ -37,6 +37,8 @@ import (
|
||||
// See https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
var allowedMimeTypes = []string{"application/", "audio/", "font/", "image/", "text/", "video/"}
|
||||
|
||||
const fileUploadPurposeMeetingNote = "meeting_note"
|
||||
|
||||
// RequestPrincipal is a tenant-scoped identity authenticated for HTTP/gRPC file access.
|
||||
type RequestPrincipal struct {
|
||||
TenantID types.TenantID
|
||||
@@ -249,6 +251,11 @@ func largeFileReceiveHTTP(wrt http.ResponseWriter, req *http.Request) {
|
||||
writeHttpResponse(ErrAuthRequired(msgID, "", now, now), nil)
|
||||
return
|
||||
}
|
||||
meetingID, meetingNoteIdempotencyKey, err := meetingNoteUploadParams(req, principal)
|
||||
if err != nil {
|
||||
writeHttpResponse(decodeStoreError(err, msgID, now, nil), err)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if uploads are handled elsewhere.
|
||||
headers, statusCode, err := mh.Headers(principal.TenantID, req.Method, req.URL, req.Header, true)
|
||||
@@ -354,16 +361,60 @@ func largeFileReceiveHTTP(wrt http.ResponseWriter, req *http.Request) {
|
||||
logs.Warn.Printf("media upload: failed to enqueue file lifecycle event file=%s: %v", fdef.Id, err)
|
||||
}
|
||||
|
||||
params := map[string]string{"url": url}
|
||||
params := map[string]any{"url": url, "file_id": fdef.Uid().String()}
|
||||
if globals.mediaGcPeriod > 0 {
|
||||
// How long this file is guaranteed to exist without being attached to a message or a topic.
|
||||
params["expires"] = now.Add(globals.mediaGcPeriod).Format(types.TimeFormatRFC3339)
|
||||
}
|
||||
if meetingID != "" {
|
||||
noteFile, err := createMeetingNoteFromUpload(principal, meetingID, meetingNoteIdempotencyKey, fdef)
|
||||
if err != nil {
|
||||
writeHttpResponse(decodeStoreError(err, msgID, now, nil), err)
|
||||
return
|
||||
}
|
||||
params["purpose"] = fileUploadPurposeMeetingNote
|
||||
params["meeting_id"] = noteFile.MeetingID
|
||||
params["note_file_id"] = noteFile.NoteFileID
|
||||
params["note_file_status"] = noteFile.Status
|
||||
params["version"] = noteFile.Version
|
||||
}
|
||||
|
||||
writeHttpResponse(NoErrParams(msgID, "", now, params), nil)
|
||||
logs.Info.Println("media upload: ok", fdef.Id, fdef.Location)
|
||||
}
|
||||
|
||||
func meetingNoteUploadParams(req *http.Request, principal RequestPrincipal) (string, string, error) {
|
||||
if strings.TrimSpace(req.FormValue("purpose")) != fileUploadPurposeMeetingNote {
|
||||
return "", "", nil
|
||||
}
|
||||
if principal.UID.IsZero() {
|
||||
return "", "", types.ErrPermissionDenied
|
||||
}
|
||||
if store.MeetingNotes == nil {
|
||||
return "", "", types.ErrUnsupported
|
||||
}
|
||||
meetingID := strings.TrimSpace(req.FormValue("meeting_id"))
|
||||
if meetingID == "" {
|
||||
return "", "", types.ErrMalformed
|
||||
}
|
||||
idempotencyKey := strings.TrimSpace(req.Header.Get("Idempotency-Key"))
|
||||
if idempotencyKey == "" {
|
||||
idempotencyKey = strings.TrimSpace(req.FormValue("id"))
|
||||
}
|
||||
if idempotencyKey == "" {
|
||||
return "", "", types.ErrMalformed
|
||||
}
|
||||
return meetingID, idempotencyKey, nil
|
||||
}
|
||||
|
||||
func createMeetingNoteFromUpload(principal RequestPrincipal, meetingID, idempotencyKey string, fdef *types.FileDef) (*types.MeetingNoteFile, error) {
|
||||
if fdef == nil || fdef.Uid().IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
noteFileID := "mnote_" + store.Store.GetUidString()
|
||||
return store.MeetingNotes.CreateFile(principal.TenantID, principal.UID, meetingID, noteFileID, fdef.Uid().String(), idempotencyKey)
|
||||
}
|
||||
|
||||
// LargeFileServe is the gRPC equivalent of largeFileServeHTTP.
|
||||
func (*grpcNodeServer) LargeFileServe(req *pbx.FileDownReq, stream pbx.Node_LargeFileServeServer) error {
|
||||
now := types.TimeNow()
|
||||
|
||||
Reference in New Issue
Block a user