github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/sharing/open_note.go (about) 1 package sharing 2 3 import ( 4 "github.com/cozy/cozy-stack/client/request" 5 "github.com/cozy/cozy-stack/model/instance" 6 "github.com/cozy/cozy-stack/model/note" 7 "github.com/cozy/cozy-stack/model/settings" 8 "github.com/cozy/cozy-stack/pkg/consts" 9 "github.com/cozy/cozy-stack/pkg/couchdb" 10 "github.com/cozy/cozy-stack/pkg/jsonapi" 11 ) 12 13 type apiNoteURL struct { 14 DocID string `json:"_id,omitempty"` 15 NoteID string `json:"note_id"` 16 Protocol string `json:"protocol"` 17 Subdomain string `json:"subdomain"` 18 Instance string `json:"instance"` 19 Sharecode string `json:"sharecode,omitempty"` 20 PublicName string `json:"public_name,omitempty"` 21 } 22 23 func (n *apiNoteURL) ID() string { return n.DocID } 24 func (n *apiNoteURL) Rev() string { return "" } 25 func (n *apiNoteURL) DocType() string { return consts.NotesURL } 26 func (n *apiNoteURL) Clone() couchdb.Doc { cloned := *n; return &cloned } 27 func (n *apiNoteURL) SetID(id string) { n.DocID = id } 28 func (n *apiNoteURL) SetRev(rev string) {} 29 func (n *apiNoteURL) Relationships() jsonapi.RelationshipMap { return nil } 30 func (n *apiNoteURL) Included() []jsonapi.Object { return nil } 31 func (n *apiNoteURL) Links() *jsonapi.LinksList { return nil } 32 func (n *apiNoteURL) Fetch(field string) []string { return nil } 33 34 // NoteOpener can be used to find the parameters for creating the URL where the 35 // note can be opened. 36 type NoteOpener struct { 37 *FileOpener 38 } 39 40 // Open will return an NoteOpener for the given file. 41 func OpenNote(inst *instance.Instance, fileID string) (*NoteOpener, error) { 42 file, err := inst.VFS().FileByID(fileID) 43 if err != nil { 44 return nil, err 45 } 46 47 // Check that the file is a note 48 if file, err = note.GetFile(inst, file); err != nil { 49 return nil, err 50 } 51 52 opener, err := NewFileOpener(inst, file) 53 if err != nil { 54 return nil, err 55 } 56 return &NoteOpener{opener}, nil 57 } 58 59 // GetResult looks if the note can be opened locally or not, which code can be 60 // used in case of a shared note, and other parameters.. and returns the information. 61 func (o *NoteOpener) GetResult(memberIndex int, readOnly bool) (jsonapi.Object, error) { 62 var result *apiNoteURL 63 var err error 64 if o.ShouldOpenLocally() { 65 result, err = o.openLocalNote(memberIndex, readOnly) 66 } else { 67 result, err = o.openSharedNote() 68 } 69 if err != nil { 70 return nil, err 71 } 72 73 // Enforce DocID and PublicName with local values 74 result.DocID = o.File.ID() 75 if name, err := settings.PublicName(o.Inst); err == nil { 76 result.PublicName = name 77 } 78 return result, nil 79 } 80 81 func (o *NoteOpener) openLocalNote(memberIndex int, readOnly bool) (*apiNoteURL, error) { 82 // If the note came from another cozy via a sharing that is now revoked, we 83 // may need to recreate the trigger. 84 // This should be taken care of when revoking the sharing now but we leave 85 // this call to make sure notes from previously revoked sharings will 86 // continue to work. 87 _ = note.SetupTrigger(o.Inst, o.File.ID()) 88 89 code, err := o.GetSharecode(memberIndex, readOnly) 90 if err != nil { 91 return nil, err 92 } 93 params := o.OpenLocalFile(code) 94 doc := apiNoteURL{ 95 NoteID: params.FileID, 96 Protocol: params.Protocol, 97 Subdomain: params.Subdomain, 98 Instance: params.Instance, 99 Sharecode: params.Sharecode, 100 } 101 return &doc, nil 102 } 103 104 func (o *NoteOpener) openSharedNote() (*apiNoteURL, error) { 105 prepared, err := o.PrepareRequestForSharedFile() 106 if err != nil { 107 return nil, err 108 } 109 if prepared.Opts == nil { 110 return o.openLocalNote(prepared.MemberIndex, prepared.ReadOnly) 111 } 112 113 prepared.Opts.Path = "/notes/" + prepared.XoredID + "/open" 114 res, err := request.Req(prepared.Opts) 115 if res != nil && res.StatusCode/100 == 4 { 116 res, err = RefreshToken(o.Inst, err, o.Sharing, prepared.Creator, 117 prepared.Creds, prepared.Opts, nil) 118 } 119 if err != nil { 120 return nil, ErrInternalServerError 121 } 122 defer res.Body.Close() 123 var doc apiNoteURL 124 if _, err := jsonapi.Bind(res.Body, &doc); err != nil { 125 return nil, err 126 } 127 return &doc, nil 128 }