github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/vfs/cozy_metadata.go (about) 1 package vfs 2 3 import ( 4 "time" 5 6 "github.com/cozy/cozy-stack/pkg/metadata" 7 ) 8 9 // DocTypeVersion represents the doctype version. Each time this document 10 // structure is modified, update this value 11 const DocTypeVersion = "1" 12 13 // UploadedByEntry is a struct with information on the app that has done the 14 // last upload of a file. 15 type UploadedByEntry struct { 16 Slug string `json:"slug,omitempty"` 17 Version string `json:"version,omitempty"` 18 Client map[string]string `json:"oauthClient,omitempty"` 19 } 20 21 // FilesCozyMetadata is an extended version of cozyMetadata with some specific fields. 22 type FilesCozyMetadata struct { 23 metadata.CozyMetadata 24 // Instance URL where the file has been created 25 CreatedOn string `json:"createdOn,omitempty"` 26 // Date of the last upload of a new content 27 UploadedAt *time.Time `json:"uploadedAt,omitempty"` 28 // Information about the last time the content was uploaded 29 UploadedBy *UploadedByEntry `json:"uploadedBy,omitempty"` 30 // Instance URL where the content has been changed the last time 31 UploadedOn string `json:"uploadedOn,omitempty"` 32 } 33 34 // NewCozyMetadata initializes a new FilesCozyMetadata struct 35 func NewCozyMetadata(instance string) *FilesCozyMetadata { 36 now := time.Now() 37 return &FilesCozyMetadata{ 38 CozyMetadata: metadata.CozyMetadata{ 39 DocTypeVersion: DocTypeVersion, 40 MetadataVersion: metadata.MetadataVersion, 41 CreatedAt: now, 42 UpdatedAt: now, 43 }, 44 CreatedOn: instance, 45 } 46 } 47 48 // Clone clones a FileCozyMetadata struct 49 func (fcm *FilesCozyMetadata) Clone() *FilesCozyMetadata { 50 cloned := *fcm 51 cloned.UpdatedByApps = make([]*metadata.UpdatedByAppEntry, len(fcm.UpdatedByApps)) 52 copy(cloned.UpdatedByApps, fcm.UpdatedByApps) 53 if fcm.UploadedBy != nil { 54 client := make(map[string]string) 55 for k, v := range fcm.UploadedBy.Client { 56 client[k] = v 57 } 58 cloned.UploadedBy = &UploadedByEntry{ 59 Slug: fcm.UploadedBy.Slug, 60 Version: fcm.UploadedBy.Version, 61 Client: client, 62 } 63 } 64 if fcm.UploadedAt != nil { 65 at := *fcm.UploadedAt 66 cloned.UploadedAt = &at 67 } 68 return &cloned 69 } 70 71 // UpdatedByApp updates the list of UpdatedByApps entries with the new entry. 72 // It ensures that each entry has a unique slug+instance, and the new entry 73 // will be in the last position. 74 func (fcm *FilesCozyMetadata) UpdatedByApp(entry *metadata.UpdatedByAppEntry) { 75 if entry.Slug == "" { 76 return 77 } 78 79 i := 0 80 seen := make(map[string]struct{}) 81 for _, app := range fcm.UpdatedByApps { 82 if app.Slug == entry.Slug && app.Instance == entry.Instance { 83 continue 84 } 85 key := app.Slug + "/" + app.Instance 86 if _, ok := seen[key]; ok { 87 continue 88 } 89 fcm.UpdatedByApps[i] = app 90 seen[key] = struct{}{} 91 i++ 92 } 93 94 fcm.UpdatedByApps = append(fcm.UpdatedByApps[:i], entry) 95 } 96 97 // ToJSONDoc returns a map with the cozyMetadata to be used inside a JSONDoc 98 // (typically for sendings sharing updates). 99 func (fcm *FilesCozyMetadata) ToJSONDoc() map[string]interface{} { 100 doc := make(map[string]interface{}) 101 doc["doctypeVersion"] = fcm.DocTypeVersion 102 doc["metadataVersion"] = fcm.MetadataVersion 103 doc["createdAt"] = fcm.CreatedAt 104 if fcm.CreatedByApp != "" { 105 doc["createdByApp"] = fcm.CreatedByApp 106 } 107 if fcm.CreatedByAppVersion != "" { 108 doc["createdByAppVersion"] = fcm.CreatedByAppVersion 109 } 110 if fcm.CreatedOn != "" { 111 doc["createdOn"] = fcm.CreatedOn 112 } 113 114 doc["updatedAt"] = fcm.UpdatedAt 115 if len(fcm.UpdatedByApps) > 0 { 116 entries := make([]map[string]interface{}, len(fcm.UpdatedByApps)) 117 for i, entry := range fcm.UpdatedByApps { 118 subdoc := map[string]interface{}{ 119 "slug": entry.Slug, 120 "date": entry.Date, 121 } 122 if entry.Version != "" { 123 subdoc["version"] = entry.Version 124 } 125 if entry.Instance != "" { 126 subdoc["instance"] = entry.Instance 127 } 128 entries[i] = subdoc 129 } 130 doc["uploadedByApp"] = entries 131 } 132 133 if fcm.UploadedAt != nil { 134 doc["uploadedAt"] = *fcm.UploadedAt 135 } 136 if fcm.UploadedBy != nil { 137 uploaded := make(map[string]interface{}) 138 if fcm.UploadedBy.Slug != "" { 139 uploaded["slug"] = fcm.UploadedBy.Slug 140 } 141 if fcm.UploadedBy.Version != "" { 142 uploaded["slug"] = fcm.UploadedBy.Version 143 } 144 if len(fcm.UploadedBy.Client) > 0 { 145 uploaded["oauthClient"] = fcm.UploadedBy.Client 146 } 147 doc["uploadedBy"] = uploaded 148 } 149 if fcm.UploadedOn != "" { 150 doc["uploadedOn"] = fcm.UploadedOn 151 } 152 if fcm.SourceAccount != "" { 153 doc["sourceAccount"] = fcm.SourceAccount 154 } 155 if fcm.SourceIdentifier != "" { 156 doc["sourceAccountIdentifier"] = fcm.SourceIdentifier 157 } 158 return doc 159 }