groupware: add bootstrapping on / with quotas for all accounts

This commit is contained in:
Pascal Bleser
2025-10-07 09:29:30 +02:00
parent 2e309f21d6
commit 776891a3ea
4 changed files with 79 additions and 44 deletions

View File

@@ -0,0 +1,70 @@
package jmap
import (
"context"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/structs"
)
type AccountBootstrapResult struct {
Identities []Identity `json:"identities,omitempty"`
Quotas []Quota `json:"quotas,omitempty"`
}
func (j *Client) GetBootstrap(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (map[string]AccountBootstrapResult, SessionState, Language, Error) {
uniqueAccountIds := structs.Uniq(accountIds)
logger = j.logger("GetIdentities", session, logger)
calls := make([]Invocation, len(uniqueAccountIds)*2)
for i, accountId := range uniqueAccountIds {
calls[i*2+0] = invocation(CommandIdentityGet, IdentityGetCommand{AccountId: accountId}, mcid(accountId, "I"))
calls[i*2+1] = invocation(CommandQuotaGet, QuotaGetCommand{AccountId: accountId}, mcid(accountId, "Q"))
}
cmd, err := j.request(session, logger, calls...)
if err != nil {
return nil, "", "", err
}
return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string]AccountBootstrapResult, Error) {
identityPerAccount := map[string][]Identity{}
quotaPerAccount := map[string][]Quota{}
for _, accountId := range uniqueAccountIds {
var identityResponse IdentityGetResponse
err = retrieveResponseMatchParameters(logger, body, CommandIdentityGet, mcid(accountId, "I"), &identityResponse)
if err != nil {
return nil, err
} else {
identityPerAccount[accountId] = identityResponse.List
}
var quotaResponse QuotaGetResponse
err = retrieveResponseMatchParameters(logger, body, CommandQuotaGet, mcid(accountId, "Q"), &quotaResponse)
if err != nil {
return nil, err
} else {
quotaPerAccount[accountId] = quotaResponse.List
}
}
result := map[string]AccountBootstrapResult{}
for accountId, value := range identityPerAccount {
r, ok := result[accountId]
if !ok {
r = AccountBootstrapResult{}
}
r.Identities = value
result[accountId] = r
}
for accountId, value := range quotaPerAccount {
r, ok := result[accountId]
if !ok {
r = AccountBootstrapResult{}
}
r.Quotas = value
result[accountId] = r
}
return result, nil
})
}

View File

@@ -4,8 +4,6 @@ import (
"net/http"
"github.com/opencloud-eu/opencloud/pkg/jmap"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/structs"
)
// When the request succeeds.
@@ -88,39 +86,3 @@ type SwaggerAccountBootstrapResponse struct {
*AccountBootstrapResponse
}
}
// swagger:route GET /groupware/accounts/{account}/bootstrap account accountbootstrap
// Get account bootstrapping.
//
// responses:
//
// 200: GetAccountBootstrapResponse200
// 400: ErrorResponse400
// 404: ErrorResponse404
// 500: ErrorResponse500
func (g *Groupware) GetAccountBootstrap(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
mailAccountId, err := req.GetAccountIdForMail()
if err != nil {
return errorResponse(err)
}
logger := log.From(req.logger.With().Str(logAccountId, mailAccountId))
accountIds := structs.Keys(req.session.Accounts)
resp, sessionState, lang, jerr := g.jmap.GetIdentitiesAndMailboxes(mailAccountId, accountIds, req.session, req.ctx, logger, req.language())
if jerr != nil {
return req.errorResponseFromJmap(jerr)
}
return response(AccountBootstrapResponse{
Version: Version,
Capabilities: Capabilities,
Limits: buildIndexLimits(req.session),
Accounts: buildIndexAccount(req.session, resp.Identities),
PrimaryAccounts: buildIndexPrimaryAccounts(req.session),
Mailboxes: map[string][]jmap.Mailbox{
mailAccountId: resp.Mailboxes,
},
}, sessionState, lang)
})
}

View File

@@ -104,6 +104,9 @@ type IndexAccount struct {
// The identities associated with this account.
Identities []jmap.Identity `json:"identities,omitempty"`
// The quotas for this account.
Quotas []jmap.Quota `json:"quotas,omitempty"`
}
type IndexPrimaryAccounts struct {
@@ -152,7 +155,7 @@ func (g *Groupware) Index(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
accountIds := structs.Keys(req.session.Accounts)
identitiesResponse, sessionState, lang, err := g.jmap.GetIdentities(accountIds, req.session, req.ctx, req.logger, req.language())
boot, sessionState, lang, err := g.jmap.GetBootstrap(accountIds, req.session, req.ctx, req.logger, req.language())
if err != nil {
return req.errorResponseFromJmap(err)
}
@@ -161,7 +164,7 @@ func (g *Groupware) Index(w http.ResponseWriter, r *http.Request) {
Version: Version,
Capabilities: Capabilities,
Limits: buildIndexLimits(req.session),
Accounts: buildIndexAccount(req.session, identitiesResponse.Identities),
Accounts: buildIndexAccount(req.session, boot),
PrimaryAccounts: buildIndexPrimaryAccounts(req.session),
}, sessionState, lang)
})
@@ -186,7 +189,7 @@ func buildIndexPrimaryAccounts(session *jmap.Session) IndexPrimaryAccounts {
}
}
func buildIndexAccount(session *jmap.Session, identities map[string][]jmap.Identity) map[string]IndexAccount {
func buildIndexAccount(session *jmap.Session, boot map[string]jmap.AccountBootstrapResult) map[string]IndexAccount {
accounts := make(map[string]IndexAccount, len(session.Accounts))
for accountId, account := range session.Accounts {
indexAccount := IndexAccount{
@@ -210,8 +213,9 @@ func buildIndexAccount(session *jmap.Session, identities map[string][]jmap.Ident
},
},
}
if identity, ok := identities[accountId]; ok {
indexAccount.Identities = identity
if b, ok := boot[accountId]; ok {
indexAccount.Identities = b.Identities
indexAccount.Quotas = b.Quotas
}
accounts[accountId] = indexAccount
}

View File

@@ -69,7 +69,6 @@ func (g *Groupware) Route(r chi.Router) {
})
r.Route("/accounts/{accountid}", func(r chi.Router) {
r.Get("/", g.GetAccount)
r.Get("/bootstrap", g.GetAccountBootstrap)
r.Get("/identities", g.GetIdentities)
r.Get("/vacation", g.GetVacation)
r.Put("/vacation", g.SetVacation)