mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-14 16:21:18 -05:00
groupware: swagger API documentation improvements
* add more documentation for properties * fixes after a bit of trial-and-error with go-swagger * fix email filter marshalling when there are no search criteria * introduce an apidoc.yml that contains Swagger data and is merged when generating the swagger.yml from sources
This commit is contained in:
@@ -19,7 +19,7 @@ func (j *Client) GetBlob(accountId string, session *Session, ctx context.Context
|
||||
aid := session.BlobAccountId(accountId)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(BlobUpload, BlobGetCommand{
|
||||
invocation(CommandBlobUpload, BlobGetCommand{
|
||||
AccountId: aid,
|
||||
Ids: []string{id},
|
||||
Properties: []string{BlobPropertyData, BlobPropertyDigestSha512, BlobPropertySize},
|
||||
@@ -31,7 +31,7 @@ func (j *Client) GetBlob(accountId string, session *Session, ctx context.Context
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (BlobResponse, Error) {
|
||||
var response BlobGetResponse
|
||||
err = retrieveResponseMatchParameters(body, BlobGet, "0", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandBlobGet, "0", &response)
|
||||
if err != nil {
|
||||
return BlobResponse{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -93,15 +93,15 @@ func (j *Client) UploadBlob(accountId string, session *Session, ctx context.Cont
|
||||
AccountId: aid,
|
||||
IdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: BlobUpload,
|
||||
Name: CommandBlobUpload,
|
||||
Path: "/ids",
|
||||
},
|
||||
Properties: []string{BlobPropertyDigestSha512},
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(BlobUpload, upload, "0"),
|
||||
invocation(BlobGet, getHash, "1"),
|
||||
invocation(CommandBlobUpload, upload, "0"),
|
||||
invocation(CommandBlobGet, getHash, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
return UploadedBlob{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -109,13 +109,13 @@ func (j *Client) UploadBlob(accountId string, session *Session, ctx context.Cont
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (UploadedBlob, Error) {
|
||||
var uploadResponse BlobUploadResponse
|
||||
err = retrieveResponseMatchParameters(body, BlobUpload, "0", &uploadResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandBlobUpload, "0", &uploadResponse)
|
||||
if err != nil {
|
||||
return UploadedBlob{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var getResponse BlobGetResponse
|
||||
err = retrieveResponseMatchParameters(body, BlobGet, "1", &getResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandBlobGet, "1", &getResponse)
|
||||
if err != nil {
|
||||
return UploadedBlob{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
@@ -40,13 +40,13 @@ func (j *Client) GetEmails(accountId string, session *Session, ctx context.Conte
|
||||
get.MaxBodyValueBytes = maxBodyValueBytes
|
||||
}
|
||||
|
||||
cmd, err := request(invocation(EmailGet, get, "0"))
|
||||
cmd, err := request(invocation(CommandEmailGet, get, "0"))
|
||||
if err != nil {
|
||||
return Emails{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
}
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (Emails, Error) {
|
||||
var response EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "0", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "0", &response)
|
||||
if err != nil {
|
||||
return Emails{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (j *Client) GetAllEmails(accountId string, session *Session, ctx context.Co
|
||||
query := EmailQueryCommand{
|
||||
AccountId: aid,
|
||||
Filter: &EmailFilterCondition{InMailbox: mailboxId},
|
||||
Sort: []Sort{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
Sort: []EmailComparator{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
CollapseThreads: true,
|
||||
CalculateTotal: true,
|
||||
}
|
||||
@@ -77,15 +77,15 @@ func (j *Client) GetAllEmails(accountId string, session *Session, ctx context.Co
|
||||
get := EmailGetRefCommand{
|
||||
AccountId: aid,
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
IdRef: &ResultReference{Name: EmailQuery, Path: "/ids/*", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandEmailQuery, Path: "/ids/*", ResultOf: "0"},
|
||||
}
|
||||
if maxBodyValueBytes >= 0 {
|
||||
get.MaxBodyValueBytes = maxBodyValueBytes
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailQuery, query, "0"),
|
||||
invocation(EmailGet, get, "1"),
|
||||
invocation(CommandEmailQuery, query, "0"),
|
||||
invocation(CommandEmailGet, get, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
return Emails{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -93,12 +93,12 @@ func (j *Client) GetAllEmails(accountId string, session *Session, ctx context.Co
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (Emails, Error) {
|
||||
var queryResponse EmailQueryResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailQuery, "0", &queryResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailQuery, "0", &queryResponse)
|
||||
if err != nil {
|
||||
return Emails{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
var getResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "1", &getResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "1", &getResponse)
|
||||
if err != nil {
|
||||
return Emails{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func (j *Client) GetEmailsInMailboxSince(accountId string, session *Session, ctx
|
||||
getCreated := EmailGetRefCommand{
|
||||
AccountId: aid,
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
IdRef: &ResultReference{Name: MailboxChanges, Path: "/created", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandMailboxChanges, Path: "/created", ResultOf: "0"},
|
||||
}
|
||||
if maxBodyValueBytes >= 0 {
|
||||
getCreated.MaxBodyValueBytes = maxBodyValueBytes
|
||||
@@ -149,16 +149,16 @@ func (j *Client) GetEmailsInMailboxSince(accountId string, session *Session, ctx
|
||||
getUpdated := EmailGetRefCommand{
|
||||
AccountId: aid,
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
IdRef: &ResultReference{Name: MailboxChanges, Path: "/updated", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandMailboxChanges, Path: "/updated", ResultOf: "0"},
|
||||
}
|
||||
if maxBodyValueBytes >= 0 {
|
||||
getUpdated.MaxBodyValueBytes = maxBodyValueBytes
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(MailboxChanges, changes, "0"),
|
||||
invocation(EmailGet, getCreated, "1"),
|
||||
invocation(EmailGet, getUpdated, "2"),
|
||||
invocation(CommandMailboxChanges, changes, "0"),
|
||||
invocation(CommandEmailGet, getCreated, "1"),
|
||||
invocation(CommandEmailGet, getUpdated, "2"),
|
||||
)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -166,19 +166,19 @@ func (j *Client) GetEmailsInMailboxSince(accountId string, session *Session, ctx
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (EmailsSince, Error) {
|
||||
var mailboxResponse MailboxChangesResponse
|
||||
err = retrieveResponseMatchParameters(body, MailboxChanges, "0", &mailboxResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandMailboxChanges, "0", &mailboxResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var createdResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "1", &createdResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "1", &createdResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var updatedResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "2", &updatedResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "2", &updatedResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func (j *Client) GetEmailsSince(accountId string, session *Session, ctx context.
|
||||
getCreated := EmailGetRefCommand{
|
||||
AccountId: aid,
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
IdRef: &ResultReference{Name: EmailChanges, Path: "/created", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandEmailChanges, Path: "/created", ResultOf: "0"},
|
||||
}
|
||||
if maxBodyValueBytes >= 0 {
|
||||
getCreated.MaxBodyValueBytes = maxBodyValueBytes
|
||||
@@ -220,16 +220,16 @@ func (j *Client) GetEmailsSince(accountId string, session *Session, ctx context.
|
||||
getUpdated := EmailGetRefCommand{
|
||||
AccountId: aid,
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
IdRef: &ResultReference{Name: EmailChanges, Path: "/updated", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandEmailChanges, Path: "/updated", ResultOf: "0"},
|
||||
}
|
||||
if maxBodyValueBytes >= 0 {
|
||||
getUpdated.MaxBodyValueBytes = maxBodyValueBytes
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailChanges, changes, "0"),
|
||||
invocation(EmailGet, getCreated, "1"),
|
||||
invocation(EmailGet, getUpdated, "2"),
|
||||
invocation(CommandEmailChanges, changes, "0"),
|
||||
invocation(CommandEmailGet, getCreated, "1"),
|
||||
invocation(CommandEmailGet, getUpdated, "2"),
|
||||
)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -237,19 +237,19 @@ func (j *Client) GetEmailsSince(accountId string, session *Session, ctx context.
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (EmailsSince, Error) {
|
||||
var changesResponse EmailChangesResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailChanges, "0", &changesResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailChanges, "0", &changesResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var createdResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "1", &createdResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "1", &createdResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var updatedResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "2", &updatedResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "2", &updatedResponse)
|
||||
if err != nil {
|
||||
return EmailsSince{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ func (j *Client) QueryEmailSnippets(accountId string, filter EmailFilterElement,
|
||||
query := EmailQueryCommand{
|
||||
AccountId: aid,
|
||||
Filter: filter,
|
||||
Sort: []Sort{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
Sort: []EmailComparator{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
CollapseThreads: true,
|
||||
CalculateTotal: true,
|
||||
}
|
||||
@@ -295,19 +295,19 @@ func (j *Client) QueryEmailSnippets(accountId string, filter EmailFilterElement,
|
||||
query.Limit = limit
|
||||
}
|
||||
|
||||
snippet := SearchSnippetRefCommand{
|
||||
snippet := SearchSnippetGetRefCommand{
|
||||
AccountId: aid,
|
||||
Filter: filter,
|
||||
EmailIdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: EmailQuery,
|
||||
Name: CommandEmailQuery,
|
||||
Path: "/ids/*",
|
||||
},
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailQuery, query, "0"),
|
||||
invocation(SearchSnippetGet, snippet, "1"),
|
||||
invocation(CommandEmailQuery, query, "0"),
|
||||
invocation(CommandSearchSnippetGet, snippet, "1"),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -316,13 +316,13 @@ func (j *Client) QueryEmailSnippets(accountId string, filter EmailFilterElement,
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (EmailSnippetQueryResult, Error) {
|
||||
var queryResponse EmailQueryResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailQuery, "0", &queryResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailQuery, "0", &queryResponse)
|
||||
if err != nil {
|
||||
return EmailSnippetQueryResult{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var snippetResponse SearchSnippetGetResponse
|
||||
err = retrieveResponseMatchParameters(body, SearchSnippetGet, "1", &snippetResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandSearchSnippetGet, "1", &snippetResponse)
|
||||
if err != nil {
|
||||
return EmailSnippetQueryResult{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -362,7 +362,7 @@ func (j *Client) QueryEmails(accountId string, filter EmailFilterElement, sessio
|
||||
query := EmailQueryCommand{
|
||||
AccountId: aid,
|
||||
Filter: filter,
|
||||
Sort: []Sort{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
Sort: []EmailComparator{{Property: emailSortByReceivedAt, IsAscending: false}},
|
||||
CollapseThreads: true,
|
||||
CalculateTotal: true,
|
||||
}
|
||||
@@ -373,12 +373,12 @@ func (j *Client) QueryEmails(accountId string, filter EmailFilterElement, sessio
|
||||
query.Limit = limit
|
||||
}
|
||||
|
||||
snippet := SearchSnippetRefCommand{
|
||||
snippet := SearchSnippetGetRefCommand{
|
||||
AccountId: aid,
|
||||
Filter: filter,
|
||||
EmailIdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: EmailQuery,
|
||||
Name: CommandEmailQuery,
|
||||
Path: "/ids/*",
|
||||
},
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func (j *Client) QueryEmails(accountId string, filter EmailFilterElement, sessio
|
||||
AccountId: aid,
|
||||
IdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: EmailQuery,
|
||||
Name: CommandEmailQuery,
|
||||
Path: "/ids/*",
|
||||
},
|
||||
FetchAllBodyValues: fetchBodies,
|
||||
@@ -395,9 +395,9 @@ func (j *Client) QueryEmails(accountId string, filter EmailFilterElement, sessio
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailQuery, query, "0"),
|
||||
invocation(SearchSnippetGet, snippet, "1"),
|
||||
invocation(EmailGet, mails, "2"),
|
||||
invocation(CommandEmailQuery, query, "0"),
|
||||
invocation(CommandSearchSnippetGet, snippet, "1"),
|
||||
invocation(CommandEmailGet, mails, "2"),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -406,19 +406,19 @@ func (j *Client) QueryEmails(accountId string, filter EmailFilterElement, sessio
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (EmailQueryResult, Error) {
|
||||
var queryResponse EmailQueryResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailQuery, "0", &queryResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailQuery, "0", &queryResponse)
|
||||
if err != nil {
|
||||
return EmailQueryResult{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var snippetResponse SearchSnippetGetResponse
|
||||
err = retrieveResponseMatchParameters(body, SearchSnippetGet, "1", &snippetResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandSearchSnippetGet, "1", &snippetResponse)
|
||||
if err != nil {
|
||||
return EmailQueryResult{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var emailsResponse EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailGet, "2", &emailsResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailGet, "2", &emailsResponse)
|
||||
if err != nil {
|
||||
return EmailQueryResult{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -485,15 +485,15 @@ func (j *Client) ImportEmail(accountId string, session *Session, ctx context.Con
|
||||
AccountId: aid,
|
||||
IdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: BlobUpload,
|
||||
Name: CommandBlobUpload,
|
||||
Path: "/ids",
|
||||
},
|
||||
Properties: []string{BlobPropertyDigestSha512},
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(BlobUpload, upload, "0"),
|
||||
invocation(BlobGet, getHash, "1"),
|
||||
invocation(CommandBlobUpload, upload, "0"),
|
||||
invocation(CommandBlobGet, getHash, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
return UploadedEmail{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -501,13 +501,13 @@ func (j *Client) ImportEmail(accountId string, session *Session, ctx context.Con
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (UploadedEmail, Error) {
|
||||
var uploadResponse BlobUploadResponse
|
||||
err = retrieveResponseMatchParameters(body, BlobUpload, "0", &uploadResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandBlobUpload, "0", &uploadResponse)
|
||||
if err != nil {
|
||||
return UploadedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var getResponse BlobGetResponse
|
||||
err = retrieveResponseMatchParameters(body, BlobGet, "1", &getResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandBlobGet, "1", &getResponse)
|
||||
if err != nil {
|
||||
return UploadedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -546,7 +546,7 @@ func (j *Client) CreateEmail(accountId string, email EmailCreate, session *Sessi
|
||||
aid := session.MailAccountId(accountId)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailSubmissionSet, EmailSetCommand{
|
||||
invocation(CommandEmailSubmissionSet, EmailSetCommand{
|
||||
AccountId: aid,
|
||||
Create: map[string]EmailCreate{
|
||||
"c": email,
|
||||
@@ -559,7 +559,7 @@ func (j *Client) CreateEmail(accountId string, email EmailCreate, session *Sessi
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (CreatedEmail, Error) {
|
||||
var setResponse EmailSetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSet, "0", &setResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSet, "0", &setResponse)
|
||||
if err != nil {
|
||||
return CreatedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -576,7 +576,7 @@ func (j *Client) CreateEmail(accountId string, email EmailCreate, session *Sessi
|
||||
|
||||
created, ok := setResponse.Created["c"]
|
||||
if !ok {
|
||||
err = fmt.Errorf("failed to find %s in %s response", string(EmailType), string(EmailSet))
|
||||
err = fmt.Errorf("failed to find %s in %s response", string(EmailType), string(CommandEmailSet))
|
||||
return CreatedEmail{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ func (j *Client) UpdateEmails(accountId string, updates map[string]EmailUpdate,
|
||||
aid := session.MailAccountId(accountId)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailSet, EmailSetCommand{
|
||||
invocation(CommandEmailSet, EmailSetCommand{
|
||||
AccountId: aid,
|
||||
Update: updates,
|
||||
}, "0"),
|
||||
@@ -617,7 +617,7 @@ func (j *Client) UpdateEmails(accountId string, updates map[string]EmailUpdate,
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (UpdatedEmails, Error) {
|
||||
var setResponse EmailSetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSet, "0", &setResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSet, "0", &setResponse)
|
||||
if err != nil {
|
||||
return UpdatedEmails{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -642,7 +642,7 @@ func (j *Client) DeleteEmails(accountId string, destroy []string, session *Sessi
|
||||
aid := session.MailAccountId(accountId)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailSet, EmailSetCommand{
|
||||
invocation(CommandEmailSet, EmailSetCommand{
|
||||
AccountId: aid,
|
||||
Destroy: destroy,
|
||||
}, "0"),
|
||||
@@ -653,7 +653,7 @@ func (j *Client) DeleteEmails(accountId string, destroy []string, session *Sessi
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (DeletedEmails, Error) {
|
||||
var setResponse EmailSetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSet, "0", &setResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSet, "0", &setResponse)
|
||||
if err != nil {
|
||||
return DeletedEmails{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -714,14 +714,14 @@ func (j *Client) SubmitEmail(accountId string, identityId string, emailId string
|
||||
AccountId: aid,
|
||||
IdRef: &ResultReference{
|
||||
ResultOf: "0",
|
||||
Name: EmailSubmissionSet,
|
||||
Name: CommandEmailSubmissionSet,
|
||||
Path: "/created/s0/id",
|
||||
},
|
||||
}
|
||||
|
||||
cmd, err := request(
|
||||
invocation(EmailSubmissionSet, set, "0"),
|
||||
invocation(EmailSubmissionGet, get, "1"),
|
||||
invocation(CommandEmailSubmissionSet, set, "0"),
|
||||
invocation(CommandEmailSubmissionGet, get, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
return SubmittedEmail{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
@@ -729,7 +729,7 @@ func (j *Client) SubmitEmail(accountId string, identityId string, emailId string
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (SubmittedEmail, Error) {
|
||||
var submissionResponse EmailSubmissionSetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSubmissionSet, "0", &submissionResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSubmissionSet, "0", &submissionResponse)
|
||||
if err != nil {
|
||||
return SubmittedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
@@ -745,13 +745,13 @@ func (j *Client) SubmitEmail(accountId string, identityId string, emailId string
|
||||
// The response to this MUST be returned after the EmailSubmission/set response."
|
||||
// from an example in the spec, it has the same tag as the EmailSubmission/set command ("0" in this case)
|
||||
var setResponse EmailSetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSet, "0", &setResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSet, "0", &setResponse)
|
||||
if err != nil {
|
||||
return SubmittedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
var getResponse EmailSubmissionGetResponse
|
||||
err = retrieveResponseMatchParameters(body, EmailSubmissionGet, "1", &getResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandEmailSubmissionGet, "1", &getResponse)
|
||||
if err != nil {
|
||||
return SubmittedEmail{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ type Identities struct {
|
||||
func (j *Client) GetIdentity(accountId string, session *Session, ctx context.Context, logger *log.Logger) (Identities, Error) {
|
||||
aid := session.MailAccountId(accountId)
|
||||
logger = j.logger(aid, "GetIdentity", session, logger)
|
||||
cmd, err := request(invocation(IdentityGet, IdentityGetCommand{AccountId: aid}, "0"))
|
||||
cmd, err := request(invocation(CommandIdentityGet, IdentityGetCommand{AccountId: aid}, "0"))
|
||||
if err != nil {
|
||||
return Identities{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
}
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (Identities, Error) {
|
||||
var response IdentityGetResponse
|
||||
err = retrieveResponseMatchParameters(body, IdentityGet, "0", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandIdentityGet, "0", &response)
|
||||
return Identities{
|
||||
Identities: response.List,
|
||||
State: response.State,
|
||||
@@ -50,7 +50,7 @@ func (j *Client) GetIdentities(accountIds []string, session *Session, ctx contex
|
||||
|
||||
calls := make([]Invocation, len(uniqueAccountIds))
|
||||
for i, accountId := range uniqueAccountIds {
|
||||
calls[i] = invocation(IdentityGet, IdentityGetCommand{AccountId: accountId}, strconv.Itoa(i))
|
||||
calls[i] = invocation(CommandIdentityGet, IdentityGetCommand{AccountId: accountId}, strconv.Itoa(i))
|
||||
}
|
||||
|
||||
cmd, err := request(calls...)
|
||||
@@ -63,7 +63,7 @@ func (j *Client) GetIdentities(accountIds []string, session *Session, ctx contex
|
||||
notFound := []string{}
|
||||
for i, accountId := range uniqueAccountIds {
|
||||
var response IdentityGetResponse
|
||||
err = retrieveResponseMatchParameters(body, IdentityGet, strconv.Itoa(i), &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandIdentityGet, strconv.Itoa(i), &response)
|
||||
if err != nil {
|
||||
return IdentitiesGetResponse{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
} else {
|
||||
|
||||
@@ -17,14 +17,14 @@ type MailboxesResponse struct {
|
||||
func (j *Client) GetMailbox(accountId string, session *Session, ctx context.Context, logger *log.Logger, ids []string) (MailboxesResponse, Error) {
|
||||
aid := session.MailAccountId(accountId)
|
||||
logger = j.logger(aid, "GetMailbox", session, logger)
|
||||
cmd, err := request(invocation(MailboxGet, MailboxGetCommand{AccountId: aid, Ids: ids}, "0"))
|
||||
cmd, err := request(invocation(CommandMailboxGet, MailboxGetCommand{AccountId: aid, Ids: ids}, "0"))
|
||||
if err != nil {
|
||||
return MailboxesResponse{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
}
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (MailboxesResponse, Error) {
|
||||
var response MailboxGetResponse
|
||||
err = retrieveResponseMatchParameters(body, MailboxGet, "0", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandMailboxGet, "0", &response)
|
||||
if err != nil {
|
||||
return MailboxesResponse{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
}
|
||||
@@ -70,10 +70,10 @@ func (j *Client) SearchMailboxes(accountId string, session *Session, ctx context
|
||||
logger = j.logger(aid, "SearchMailboxes", session, logger)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(MailboxQuery, MailboxQueryCommand{AccountId: aid, Filter: filter}, "0"),
|
||||
invocation(MailboxGet, MailboxGetRefCommand{
|
||||
invocation(CommandMailboxQuery, MailboxQueryCommand{AccountId: aid, Filter: filter}, "0"),
|
||||
invocation(CommandMailboxGet, MailboxGetRefCommand{
|
||||
AccountId: aid,
|
||||
IdRef: &ResultReference{Name: MailboxQuery, Path: "/ids/*", ResultOf: "0"},
|
||||
IdRef: &ResultReference{Name: CommandMailboxQuery, Path: "/ids/*", ResultOf: "0"},
|
||||
}, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -82,7 +82,7 @@ func (j *Client) SearchMailboxes(accountId string, session *Session, ctx context
|
||||
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (Mailboxes, Error) {
|
||||
var response MailboxGetResponse
|
||||
err = retrieveResponseMatchParameters(body, MailboxGet, "1", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandMailboxGet, "1", &response)
|
||||
if err != nil {
|
||||
return Mailboxes{}, SimpleError{code: JmapErrorInvalidJmapResponsePayload, err: err}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ const (
|
||||
func (j *Client) GetVacationResponse(accountId string, session *Session, ctx context.Context, logger *log.Logger) (VacationResponseGetResponse, Error) {
|
||||
aid := session.MailAccountId(accountId)
|
||||
logger = j.logger(aid, "GetVacationResponse", session, logger)
|
||||
cmd, err := request(invocation(VacationResponseGet, VacationResponseGetCommand{AccountId: aid}, "0"))
|
||||
cmd, err := request(invocation(CommandVacationResponseGet, VacationResponseGetCommand{AccountId: aid}, "0"))
|
||||
if err != nil {
|
||||
return VacationResponseGetResponse{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
}
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (VacationResponseGetResponse, Error) {
|
||||
var response VacationResponseGetResponse
|
||||
err = retrieveResponseMatchParameters(body, VacationResponseGet, "0", &response)
|
||||
err = retrieveResponseMatchParameters(body, CommandVacationResponseGet, "0", &response)
|
||||
return response, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
})
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func (j *Client) SetVacationResponse(accountId string, vacation VacationResponse
|
||||
logger = j.logger(aid, "SetVacationResponse", session, logger)
|
||||
|
||||
cmd, err := request(
|
||||
invocation(VacationResponseSet, VacationResponseSetCommand{
|
||||
invocation(CommandVacationResponseSet, VacationResponseSetCommand{
|
||||
AccountId: aid,
|
||||
Create: map[string]VacationResponse{
|
||||
vacationResponseId: {
|
||||
@@ -77,14 +77,14 @@ func (j *Client) SetVacationResponse(accountId string, vacation VacationResponse
|
||||
}, "0"),
|
||||
// chain a second request to get the current complete VacationResponse object
|
||||
// after performing the changes, as that makes for a better API
|
||||
invocation(VacationResponseGet, VacationResponseGetCommand{AccountId: aid}, "1"),
|
||||
invocation(CommandVacationResponseGet, VacationResponseGetCommand{AccountId: aid}, "1"),
|
||||
)
|
||||
if err != nil {
|
||||
return VacationResponseChange{}, SimpleError{code: JmapErrorInvalidJmapRequestPayload, err: err}
|
||||
}
|
||||
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, func(body *Response) (VacationResponseChange, Error) {
|
||||
var setResponse VacationResponseSetResponse
|
||||
err = retrieveResponseMatchParameters(body, VacationResponseSet, "0", &setResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandVacationResponseSet, "0", &setResponse)
|
||||
if err != nil {
|
||||
return VacationResponseChange{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
}
|
||||
@@ -96,13 +96,13 @@ func (j *Client) SetVacationResponse(accountId string, vacation VacationResponse
|
||||
}
|
||||
|
||||
var getResponse VacationResponseGetResponse
|
||||
err = retrieveResponseMatchParameters(body, VacationResponseGet, "1", &getResponse)
|
||||
err = retrieveResponseMatchParameters(body, CommandVacationResponseGet, "1", &getResponse)
|
||||
if err != nil {
|
||||
return VacationResponseChange{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
}
|
||||
|
||||
if len(getResponse.List) != 1 {
|
||||
err = fmt.Errorf("failed to find %s in %s response", string(VacationResponseType), string(VacationResponseGet))
|
||||
err = fmt.Errorf("failed to find %s in %s response", string(VacationResponseType), string(CommandVacationResponseGet))
|
||||
return VacationResponseChange{}, simpleError(err, JmapErrorInvalidJmapResponsePayload)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,5 +60,8 @@ func (j *Client) loggerParams(accountId string, operation string, session *Sessi
|
||||
if accountId != "" {
|
||||
l = l.Str(logAccountId, accountId)
|
||||
}
|
||||
if params != nil {
|
||||
l = params(l)
|
||||
}
|
||||
return log.From(l)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
package jmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
@@ -43,46 +43,46 @@ type Session struct {
|
||||
// The upload URL template
|
||||
DownloadUrlTemplate string
|
||||
|
||||
// TODO
|
||||
DefaultMailAccountId string
|
||||
|
||||
SessionResponse
|
||||
}
|
||||
|
||||
var (
|
||||
invalidSessionResponseErrorMissingUsername = SimpleError{code: JmapErrorInvalidSessionResponse, err: errors.New("JMAP session response does not provide a username")}
|
||||
invalidSessionResponseErrorMissingApiUrl = SimpleError{code: JmapErrorInvalidSessionResponse, err: errors.New("JMAP session response does not provide an API URL")}
|
||||
invalidSessionResponseErrorInvalidApiUrl = SimpleError{code: JmapErrorInvalidSessionResponse, err: errors.New("JMAP session response provides an invalid API URL")}
|
||||
invalidSessionResponseErrorMissingUploadUrl = SimpleError{code: JmapErrorInvalidSessionResponse, err: errors.New("JMAP session response does not provide an upload URL")}
|
||||
invalidSessionResponseErrorMissingDownloadUrl = SimpleError{code: JmapErrorInvalidSessionResponse, err: errors.New("JMAP session response does not provide a download URL")}
|
||||
)
|
||||
|
||||
// Create a new Session from a SessionResponse.
|
||||
func newSession(sessionResponse SessionResponse) (Session, Error) {
|
||||
username := sessionResponse.Username
|
||||
if username == "" {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response does not provide a username")}
|
||||
}
|
||||
mailAccountId := sessionResponse.PrimaryAccounts.Mail
|
||||
if mailAccountId == "" {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response does not provide a primary mail account")}
|
||||
return Session{}, invalidSessionResponseErrorMissingUsername
|
||||
}
|
||||
apiStr := sessionResponse.ApiUrl
|
||||
if apiStr == "" {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response does not provide an API URL")}
|
||||
return Session{}, invalidSessionResponseErrorMissingApiUrl
|
||||
}
|
||||
apiUrl, err := url.Parse(apiStr)
|
||||
if err != nil {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response provides an invalid API URL")}
|
||||
return Session{}, invalidSessionResponseErrorInvalidApiUrl
|
||||
}
|
||||
uploadUrl := sessionResponse.UploadUrl
|
||||
if uploadUrl == "" {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response does not provide an upload URL")}
|
||||
return Session{}, invalidSessionResponseErrorMissingUploadUrl
|
||||
}
|
||||
downloadUrl := sessionResponse.DownloadUrl
|
||||
if downloadUrl == "" {
|
||||
return Session{}, SimpleError{code: JmapErrorInvalidSessionResponse, err: fmt.Errorf("JMAP session response does not provide an download URL")}
|
||||
return Session{}, invalidSessionResponseErrorMissingDownloadUrl
|
||||
}
|
||||
|
||||
return Session{
|
||||
Username: username,
|
||||
DefaultMailAccountId: mailAccountId,
|
||||
JmapUrl: *apiUrl,
|
||||
UploadUrlTemplate: uploadUrl,
|
||||
DownloadUrlTemplate: downloadUrl,
|
||||
SessionResponse: sessionResponse,
|
||||
Username: username,
|
||||
JmapUrl: *apiUrl,
|
||||
UploadUrlTemplate: uploadUrl,
|
||||
DownloadUrlTemplate: downloadUrl,
|
||||
SessionResponse: sessionResponse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func (s *Session) MailAccountId(accountId string) string {
|
||||
return accountId
|
||||
}
|
||||
// TODO(pbleser-oc) handle case where there is no default mail account
|
||||
return s.DefaultMailAccountId
|
||||
return s.PrimaryAccounts.Mail
|
||||
}
|
||||
|
||||
func (s *Session) BlobAccountId(accountId string) string {
|
||||
|
||||
@@ -115,9 +115,9 @@ func serveTestFile(t *testing.T, name string) ([]byte, Error) {
|
||||
func (t *TestJmapApiClient) Command(ctx context.Context, logger *log.Logger, session *Session, request Request) ([]byte, Error) {
|
||||
command := request.MethodCalls[0].Command
|
||||
switch command {
|
||||
case MailboxGet:
|
||||
case CommandMailboxGet:
|
||||
return serveTestFile(t.t, "mailboxes1.json")
|
||||
case EmailQuery:
|
||||
case CommandEmailQuery:
|
||||
return serveTestFile(t.t, "mails1.json")
|
||||
default:
|
||||
require.Fail(t.t, "TestJmapApiClient: unsupported jmap command: %v", command)
|
||||
@@ -149,7 +149,7 @@ func TestRequests(t *testing.T) {
|
||||
jmapUrl, err := url.Parse("http://localhost/jmap")
|
||||
require.NoError(err)
|
||||
|
||||
session := Session{DefaultMailAccountId: "123", Username: "user123", JmapUrl: *jmapUrl}
|
||||
session := Session{Username: "user123", JmapUrl: *jmapUrl}
|
||||
|
||||
folders, err := client.GetAllMailboxes("a", &session, ctx, &logger)
|
||||
require.NoError(err)
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestDeserializeMailboxGetResponse(t *testing.T) {
|
||||
require.Equal("3e25b2a0", data.SessionState)
|
||||
require.Len(data.MethodResponses, 1)
|
||||
resp := data.MethodResponses[0]
|
||||
require.Equal(MailboxGet, resp.Command)
|
||||
require.Equal(CommandMailboxGet, resp.Command)
|
||||
require.Equal("0", resp.Tag)
|
||||
require.IsType(MailboxGetResponse{}, resp.Parameters)
|
||||
mgr := resp.Parameters.(MailboxGetResponse)
|
||||
@@ -75,7 +75,7 @@ func TestDeserializeEmailGetResponse(t *testing.T) {
|
||||
require.Equal("3e25b2a0", data.SessionState)
|
||||
require.Len(data.MethodResponses, 2)
|
||||
resp := data.MethodResponses[1]
|
||||
require.Equal(EmailGet, resp.Command)
|
||||
require.Equal(CommandEmailGet, resp.Command)
|
||||
require.Equal("1", resp.Tag)
|
||||
require.IsType(EmailGetResponse{}, resp.Parameters)
|
||||
egr := resp.Parameters.(EmailGetResponse)
|
||||
|
||||
@@ -14,8 +14,8 @@ include ../../.make/docs.mk
|
||||
apidoc: swagger.yml
|
||||
|
||||
.PHONY: swagger.yml
|
||||
swagger.yml:
|
||||
swagger generate spec -c groupware -o ./swagger.yml
|
||||
swagger.yml: apidoc.yml
|
||||
swagger generate spec --output=$@ --include='groupware' --include='jmap' --scan-models --input=$<
|
||||
|
||||
APIDOC_PORT=9999
|
||||
|
||||
|
||||
9
services/groupware/apidoc.yml
Normal file
9
services/groupware/apidoc.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
tags:
|
||||
- name: init
|
||||
description: Initialization APIs
|
||||
- name: mailboxes
|
||||
description: APIs that pertain to mailboxes
|
||||
- name: messages
|
||||
description: APIs about emails
|
||||
- name: vacation
|
||||
description: APIs about vacation responses
|
||||
@@ -2,8 +2,28 @@ package groupware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
)
|
||||
|
||||
// When the request suceeds.
|
||||
// swagger:response GetIdentitiesResponse
|
||||
type SwaggerGetIdentitiesResponse struct {
|
||||
// in: body
|
||||
Body struct {
|
||||
*jmap.Identities
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /accounts/{accountid}/identities identities identities
|
||||
// Get the list of identities that are associated with an account.
|
||||
//
|
||||
// responses:
|
||||
//
|
||||
// 200: GetIdentitiesResponse
|
||||
// 400: ErrorResponse400
|
||||
// 404: ErrorResponse404
|
||||
// 500: ErrorResponse500
|
||||
func (g Groupware) GetIdentities(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
res, err := g.jmap.GetIdentity(req.GetAccountId(), req.session, req.ctx, req.logger)
|
||||
|
||||
@@ -9,24 +9,76 @@ import (
|
||||
|
||||
type IndexLimits struct {
|
||||
// The maximum file size, in octets, that the server will accept for a single file upload (for any purpose).
|
||||
MaxSizeUpload int `json:"maxSizeUpload"`
|
||||
MaxConcurrentUpload int `json:"maxConcurrentUpload"`
|
||||
MaxSizeRequest int `json:"maxSizeRequest"`
|
||||
MaxSizeUpload int `json:"maxSizeUpload"`
|
||||
|
||||
// The maximum number of concurrent requests the server will accept to the upload endpoint.
|
||||
MaxConcurrentUpload int `json:"maxConcurrentUpload"`
|
||||
|
||||
// The maximum size, in octets, that the server will accept for a single request to the API endpoint.
|
||||
MaxSizeRequest int `json:"maxSizeRequest"`
|
||||
|
||||
// The maximum number of concurrent requests the server will accept to the API endpoint.
|
||||
MaxConcurrentRequests int `json:"maxConcurrentRequests"`
|
||||
}
|
||||
|
||||
type IndexAccountMailCapabilities struct {
|
||||
MaxMailboxDepth int `json:"maxMailboxDepth"`
|
||||
MaxSizeMailboxName int `json:"maxSizeMailboxName"`
|
||||
MaxSizeAttachmentsPerEmail int `json:"maxSizeAttachmentsPerEmail"`
|
||||
MayCreateTopLevelMailbox bool `json:"mayCreateTopLevelMailbox"`
|
||||
MaxDelayedSend int `json:"maxDelayedSend"`
|
||||
// The maximum depth of the Mailbox hierarchy (i.e., one more than the maximum number of ancestors
|
||||
// a Mailbox may have), or null for no limit.
|
||||
MaxMailboxDepth int `json:"maxMailboxDepth"`
|
||||
|
||||
// The maximum length, in (UTF-8) octets, allowed for the name of a Mailbox.
|
||||
//
|
||||
// This MUST be at least 100, although it is recommended servers allow more.
|
||||
MaxSizeMailboxName int `json:"maxSizeMailboxName"`
|
||||
|
||||
// The maximum number of Mailboxes that can be can assigned to a single Email object.
|
||||
//
|
||||
// This MUST be an integer >= 1, or null for no limit (or rather, the limit is always the number of
|
||||
// Mailboxes in the account).
|
||||
MaxMailboxesPerEmail int `json:"maxMailboxesPerEmail"`
|
||||
|
||||
// The maximum total size of attachments, in octets, allowed for a single Email object.
|
||||
//
|
||||
// A server MAY still reject the import or creation of an Email with a lower attachment size total
|
||||
// (for example, if the body includes several megabytes of text, causing the size of the encoded
|
||||
// MIME structure to be over some server-defined limit).
|
||||
//
|
||||
// Note that this limit is for the sum of unencoded attachment sizes. Users are generally not
|
||||
// knowledgeable about encoding overhead, etc., nor should they need to be, so marketing and help
|
||||
// materials normally tell them the “max size attachments”. This is the unencoded size they see
|
||||
// on their hard drive, so this capability matches that and allows the client to consistently
|
||||
// enforce what the user understands as the limit.
|
||||
MaxSizeAttachmentsPerEmail int `json:"maxSizeAttachmentsPerEmail"`
|
||||
|
||||
// If true, the user may create a Mailbox in this account with a null parentId.
|
||||
MayCreateTopLevelMailbox bool `json:"mayCreateTopLevelMailbox"`
|
||||
|
||||
// The number in seconds of the maximum delay the server supports in sending.
|
||||
//
|
||||
// This is 0 if the server does not support delayed send.
|
||||
MaxDelayedSend int `json:"maxDelayedSend"`
|
||||
}
|
||||
|
||||
type IndexAccountSieveCapabilities struct {
|
||||
MaxSizeScriptName int `json:"maxSizeScriptName"`
|
||||
MaxSizeScript int `json:"maxSizeScript"`
|
||||
MaxNumberScripts int `json:"maxNumberScripts"`
|
||||
// The maximum length, in octets, allowed for the name of a SieveScript.
|
||||
//
|
||||
// For compatibility with ManageSieve, this MUST be at least 512 (up
|
||||
// to 128 Unicode characters).
|
||||
MaxSizeScriptName int `json:"maxSizeScriptName"`
|
||||
|
||||
// The maximum size (in octets) of a Sieve script the server is willing
|
||||
// to store for the user, or null for no limit.
|
||||
MaxSizeScript int `json:"maxSizeScript"`
|
||||
|
||||
// The maximum number of Sieve scripts the server is willing to store
|
||||
// for the user, or null for no limit.
|
||||
MaxNumberScripts int `json:"maxNumberScripts"`
|
||||
|
||||
// The maximum number of Sieve "redirect" actions a script can perform
|
||||
// during a single evaluation, or null for no limit.
|
||||
//
|
||||
// Note that this is different from the total number of "redirect"
|
||||
// actions a script can contain.
|
||||
MaxNumberRedirects int `json:"maxNumberRedirects"`
|
||||
}
|
||||
|
||||
@@ -36,24 +88,49 @@ type IndexAccountCapabilities struct {
|
||||
}
|
||||
|
||||
type IndexAccount struct {
|
||||
Name string `json:"name"`
|
||||
IsPersonal bool `json:"isPersonal"`
|
||||
IsReadOnly bool `json:"isReadOnly"`
|
||||
// A user-friendly string to show when presenting content from this account,
|
||||
// e.g., the email address representing the owner of the account.
|
||||
Name string `json:"name"`
|
||||
|
||||
// This is true if the account belongs to the authenticated user rather than
|
||||
// a group account or a personal account of another user that has been shared
|
||||
// with them.
|
||||
IsPersonal bool `json:"isPersonal"`
|
||||
|
||||
// This is true if the entire account is read-only.
|
||||
IsReadOnly bool `json:"isReadOnly"`
|
||||
|
||||
Capabilities IndexAccountCapabilities `json:"capabilities"`
|
||||
Identities []jmap.Identity `json:"identities,omitempty"`
|
||||
|
||||
// The identities associated with this account.
|
||||
Identities []jmap.Identity `json:"identities,omitempty"`
|
||||
}
|
||||
|
||||
type IndexPrimaryAccounts struct {
|
||||
Mail string `json:"mail"`
|
||||
Submission string `json:"submission"`
|
||||
Mail string `json:"mail"`
|
||||
Submission string `json:"submission"`
|
||||
Blob string `json:"blob"`
|
||||
VacationResponse string `json:"vacationResponse"`
|
||||
Sieve string `json:"sieve"`
|
||||
}
|
||||
|
||||
type IndexResponse struct {
|
||||
Version string `json:"version"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
Limits IndexLimits `json:"limits"`
|
||||
Accounts map[string]IndexAccount `json:"accounts"`
|
||||
PrimaryAccounts IndexPrimaryAccounts `json:"primaryAccounts"`
|
||||
// The API version.
|
||||
Version string `json:"version"`
|
||||
|
||||
// A list of capabilities of this API version.
|
||||
Capabilities []string `json:"capabilities"`
|
||||
|
||||
// API limits.
|
||||
Limits IndexLimits `json:"limits"`
|
||||
|
||||
// Accounts that are available to the user.
|
||||
//
|
||||
// The key of the mapis the identifier.
|
||||
Accounts map[string]IndexAccount `json:"accounts"`
|
||||
|
||||
// Primary accounts for usage types.
|
||||
PrimaryAccounts IndexPrimaryAccounts `json:"primaryAccounts"`
|
||||
}
|
||||
|
||||
// When the request suceeds.
|
||||
@@ -65,8 +142,8 @@ type SwaggerIndexResponse struct {
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET / index
|
||||
// Get initial bootup information
|
||||
// swagger:route GET / init index
|
||||
// Get initial bootstrapping information for a user.
|
||||
//
|
||||
// responses:
|
||||
//
|
||||
@@ -97,6 +174,7 @@ func (g Groupware) Index(w http.ResponseWriter, r *http.Request) {
|
||||
Mail: IndexAccountMailCapabilities{
|
||||
MaxMailboxDepth: account.AccountCapabilities.Mail.MaxMailboxDepth,
|
||||
MaxSizeMailboxName: account.AccountCapabilities.Mail.MaxSizeMailboxName,
|
||||
MaxMailboxesPerEmail: account.AccountCapabilities.Mail.MaxMailboxesPerEmail,
|
||||
MaxSizeAttachmentsPerEmail: account.AccountCapabilities.Mail.MaxSizeAttachmentsPerEmail,
|
||||
MayCreateTopLevelMailbox: account.AccountCapabilities.Mail.MayCreateTopLevelMailbox,
|
||||
MaxDelayedSend: account.AccountCapabilities.Submission.MaxDelayedSend,
|
||||
@@ -126,8 +204,11 @@ func (g Groupware) Index(w http.ResponseWriter, r *http.Request) {
|
||||
},
|
||||
Accounts: accounts,
|
||||
PrimaryAccounts: IndexPrimaryAccounts{
|
||||
Mail: req.session.PrimaryAccounts.Mail,
|
||||
Submission: req.session.PrimaryAccounts.Submission,
|
||||
Mail: req.session.PrimaryAccounts.Mail,
|
||||
Submission: req.session.PrimaryAccounts.Submission,
|
||||
Blob: req.session.PrimaryAccounts.Blob,
|
||||
VacationResponse: req.session.PrimaryAccounts.VacationResponse,
|
||||
Sieve: req.session.PrimaryAccounts.Sieve,
|
||||
},
|
||||
}, req.session.State)
|
||||
})
|
||||
|
||||
@@ -18,7 +18,7 @@ type SwaggerGetMailboxById200 struct {
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /accounts/{account}/mailboxes/{id} mailboxes_by_id
|
||||
// swagger:route GET /accounts/{account}/mailboxes/{id} mailboxes mailboxes_by_id
|
||||
// Get a specific mailbox by its identifier.
|
||||
//
|
||||
// A Mailbox represents a named set of Emails.
|
||||
@@ -73,7 +73,7 @@ type SwaggerMailboxesResponse200 struct {
|
||||
Body []jmap.Mailbox
|
||||
}
|
||||
|
||||
// swagger:route GET /accounts/{account}/mailboxes mailboxes
|
||||
// swagger:route GET /accounts/{account}/mailboxes mailboxes mailboxes
|
||||
// Get the list of all the mailboxes of an account.
|
||||
//
|
||||
// A Mailbox represents a named set of Emails.
|
||||
|
||||
@@ -12,6 +12,45 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
)
|
||||
|
||||
// When the request succeeds without a "since" query parameter.
|
||||
// swagger:response GetAllMessagesInMailbox200
|
||||
type SwaggerGetAllMessagesInMailbox200 struct {
|
||||
// in: body
|
||||
Body struct {
|
||||
*jmap.Emails
|
||||
}
|
||||
}
|
||||
|
||||
// When the request succeeds with a "since" query parameter.
|
||||
// swagger:response GetAllMessagesInMailboxSince200
|
||||
type SwaggerGetAllMessagesInMailboxSince200 struct {
|
||||
// in: body
|
||||
Body struct {
|
||||
*jmap.EmailsSince
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /accounts/{account}/mailboxes/{id}/messages messages get_all_messages_in_mailbox
|
||||
// Get all the emails in a mailbox.
|
||||
//
|
||||
// Retrieve the list of all the emails that are in a given mailbox.
|
||||
//
|
||||
// The mailbox must be specified by its id, as part of the request URL path.
|
||||
//
|
||||
// A limit and an offset may be specified using the query parameters 'limit' and 'offset',
|
||||
// respectively.
|
||||
//
|
||||
// When the query parameter 'since' or the 'if-none-match' header is specified, then the
|
||||
// request behaves differently, performing a changes query to determine what has changed in
|
||||
// that mailbox since a given state identifier.
|
||||
//
|
||||
// responses:
|
||||
//
|
||||
// 200: GetAllMessagesInMailbox200
|
||||
// 200: GetAllMessagesInMailboxSince200
|
||||
// 400: ErrorResponse400
|
||||
// 404: ErrorResponse404
|
||||
// 500: ErrorResponse500
|
||||
func (g Groupware) GetAllMessagesInMailbox(w http.ResponseWriter, r *http.Request) {
|
||||
mailboxId := chi.URLParam(r, UriParamMailboxId)
|
||||
since := r.Header.Get(HeaderSince)
|
||||
@@ -144,7 +183,7 @@ type MessageSearchResults struct {
|
||||
QueryState string `json:"queryState,omitempty"`
|
||||
}
|
||||
|
||||
func (g Groupware) buildQuery(req Request) (bool, jmap.EmailFilterElement, int, int, *log.Logger, Response) {
|
||||
func (g Groupware) buildFilter(req Request) (bool, jmap.EmailFilterElement, int, int, *log.Logger, Response) {
|
||||
q := req.r.URL.Query()
|
||||
mailboxId := q.Get(QueryParamMailboxId)
|
||||
notInMailboxIds := q[QueryParamNotInMailboxId]
|
||||
@@ -270,22 +309,19 @@ func (g Groupware) buildQuery(req Request) (bool, jmap.EmailFilterElement, int,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true, filter, offset, limit, logger, Response{}
|
||||
}
|
||||
|
||||
func (g Groupware) searchMessages(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
ok, filter, offset, limit, logger, errResp := g.buildQuery(req)
|
||||
ok, filter, offset, limit, logger, errResp := g.buildFilter(req)
|
||||
if !ok {
|
||||
return errResp
|
||||
}
|
||||
|
||||
var empty jmap.EmailFilterElement
|
||||
|
||||
if filter == empty {
|
||||
errorId := req.errorId()
|
||||
msg := "Invalid search request has no criteria"
|
||||
return errorResponse(apiError(errorId, ErrorInvalidUserRequest, withDetail(msg)))
|
||||
if !filter.IsNotEmpty() {
|
||||
filter = nil
|
||||
}
|
||||
|
||||
fetchEmails, ok, err := req.parseBoolParam(QueryParamSearchFetchEmails, false)
|
||||
@@ -293,7 +329,7 @@ func (g Groupware) searchMessages(w http.ResponseWriter, r *http.Request) {
|
||||
return errorResponse(err)
|
||||
}
|
||||
if ok {
|
||||
logger = &log.Logger{Logger: logger.With().Bool(QueryParamSearchFetchEmails, fetchEmails).Logger()}
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchEmails, fetchEmails))
|
||||
}
|
||||
|
||||
if fetchEmails {
|
||||
@@ -302,7 +338,7 @@ func (g Groupware) searchMessages(w http.ResponseWriter, r *http.Request) {
|
||||
return errorResponse(err)
|
||||
}
|
||||
if ok {
|
||||
logger = &log.Logger{Logger: logger.With().Bool(QueryParamSearchFetchBodies, fetchBodies).Logger()}
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchBodies, fetchBodies))
|
||||
}
|
||||
|
||||
results, jerr := g.jmap.QueryEmails(req.GetAccountId(), filter, req.session, req.ctx, logger, offset, limit, fetchBodies, g.maxBodyValueBytes)
|
||||
@@ -424,7 +460,7 @@ func (g Groupware) UpdateMessage(w http.ResponseWriter, r *http.Request) {
|
||||
l := req.logger.With()
|
||||
l.Str(UriParamMessageId, messageId)
|
||||
|
||||
logger := &log.Logger{Logger: l.Logger()}
|
||||
logger := log.From(l)
|
||||
|
||||
var body map[string]any
|
||||
err := req.body(&body)
|
||||
@@ -463,7 +499,7 @@ func (g Groupware) DeleteMessage(w http.ResponseWriter, r *http.Request) {
|
||||
l := req.logger.With()
|
||||
l.Str(UriParamMessageId, messageId)
|
||||
|
||||
logger := &log.Logger{Logger: l.Logger()}
|
||||
logger := log.From(l)
|
||||
|
||||
deleted, jerr := g.jmap.DeleteEmails(req.GetAccountId(), []string{messageId}, req.session, req.ctx, logger)
|
||||
if jerr != nil {
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
)
|
||||
|
||||
// When the request succeeds.
|
||||
// swagger:response VacationResponse200
|
||||
type SwaggerVacationResponse200 struct {
|
||||
// swagger:response GetVacationResponse200
|
||||
type SwaggerGetVacationResponse200 struct {
|
||||
// in: body
|
||||
Body struct {
|
||||
*jmap.VacationResponseGetResponse
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /accounts/{account}/vacation vacation
|
||||
// swagger:route GET /accounts/{account}/vacation vacation getvacation
|
||||
// Get vacation notice information.
|
||||
//
|
||||
// A vacation response sends an automatic reply when a message is delivered to the mail store, informing the original
|
||||
@@ -25,7 +25,7 @@ type SwaggerVacationResponse200 struct {
|
||||
//
|
||||
// responses:
|
||||
//
|
||||
// 200: VacationResponse200
|
||||
// 200: GetVacationResponse200
|
||||
// 400: ErrorResponse400
|
||||
// 500: ErrorResponse500
|
||||
func (g Groupware) GetVacation(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -38,6 +38,26 @@ func (g Groupware) GetVacation(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// When the request succeeds.
|
||||
// swagger:response SetVacationResponse200
|
||||
type SwaggerSetVacationResponse200 struct {
|
||||
// in: body
|
||||
Body struct {
|
||||
*jmap.VacationResponseChange
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route PUT /accounts/{account}/vacation vacation setvacation
|
||||
// Set the vacation notice information.
|
||||
//
|
||||
// A vacation response sends an automatic reply when a message is delivered to the mail store, informing the original
|
||||
// sender that their message may not be read for some time.
|
||||
//
|
||||
// responses:
|
||||
//
|
||||
// 200: SetVacationResponse200
|
||||
// 400: ErrorResponse400
|
||||
// 500: ErrorResponse500
|
||||
func (g Groupware) SetVacation(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
var body jmap.VacationResponsePayload
|
||||
|
||||
@@ -54,7 +54,8 @@ func (g Groupware) Route(r chi.Router) {
|
||||
r.Get("/", g.GetMessages) // ?fetchemails=true&fetchbodies=true&text=&subject=&body=&keyword=&keyword=&...
|
||||
r.Post("/", g.CreateMessage)
|
||||
r.Get("/{messageid}", g.GetMessagesById)
|
||||
r.Put("/{messageid}", g.UpdateMessage) // or PATCH?
|
||||
// r.Put("/{messageid}", g.ReplaceMessage) // TODO
|
||||
r.Patch("/{messageid}", g.UpdateMessage)
|
||||
r.Delete("/{messageId}", g.DeleteMessage)
|
||||
})
|
||||
r.Route("/blobs", func(r chi.Router) {
|
||||
|
||||
Reference in New Issue
Block a user