From 940cd81083d2e0b4e65dde7ba4cdaedeebc08f4e Mon Sep 17 00:00:00 2001
From: Pascal Bleser
Date: Mon, 6 Oct 2025 16:14:24 +0200
Subject: [PATCH] groupware: add /quota for all accounts
---
pkg/jmap/jmap_api_quota.go | 32 +++++++----
.../pkg/groupware/groupware_api_quota.go | 54 +++++++++++++++++--
.../pkg/groupware/groupware_route.go | 1 +
3 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/pkg/jmap/jmap_api_quota.go b/pkg/jmap/jmap_api_quota.go
index a8082ca80..3c8f0f6e2 100644
--- a/pkg/jmap/jmap_api_quota.go
+++ b/pkg/jmap/jmap_api_quota.go
@@ -4,20 +4,32 @@ import (
"context"
"github.com/opencloud-eu/opencloud/pkg/log"
+ "github.com/opencloud-eu/opencloud/pkg/structs"
)
-func (j *Client) GetQuotas(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (QuotaGetResponse, SessionState, Language, Error) {
+func (j *Client) GetQuotas(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (map[string]QuotaGetResponse, SessionState, Language, Error) {
logger = j.logger("GetQuotas", session, logger)
- cmd, err := j.request(session, logger, invocation(CommandQuotaGet, QuotaGetCommand{AccountId: accountId}, "0"))
- if err != nil {
- return QuotaGetResponse{}, "", "", err
+
+ uniqueAccountIds := structs.Uniq(accountIds)
+
+ invocations := make([]Invocation, len(uniqueAccountIds))
+ for i, accountId := range uniqueAccountIds {
+ invocations[i] = invocation(CommandQuotaGet, MailboxQueryCommand{AccountId: accountId}, mcid(accountId, "0"))
}
- return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (QuotaGetResponse, Error) {
- var response QuotaGetResponse
- err = retrieveResponseMatchParameters(logger, body, CommandQuotaGet, "0", &response)
- if err != nil {
- return QuotaGetResponse{}, err
+ cmd, err := j.request(session, logger, invocations...)
+ if err != nil {
+ return nil, "", "", err
+ }
+ return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string]QuotaGetResponse, Error) {
+ result := map[string]QuotaGetResponse{}
+ for _, accountId := range uniqueAccountIds {
+ var response QuotaGetResponse
+ err = retrieveResponseMatchParameters(logger, body, CommandQuotaGet, mcid(accountId, "0"), &response)
+ if err != nil {
+ return nil, err
+ }
+ result[accountId] = response
}
- return response, nil
+ return result, nil
})
}
diff --git a/services/groupware/pkg/groupware/groupware_api_quota.go b/services/groupware/pkg/groupware/groupware_api_quota.go
index eebf6c148..bf0832abe 100644
--- a/services/groupware/pkg/groupware/groupware_api_quota.go
+++ b/services/groupware/pkg/groupware/groupware_api_quota.go
@@ -5,6 +5,7 @@ import (
"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.
@@ -14,7 +15,7 @@ type SwaggerGetQuotaResponse200 struct {
Body []jmap.Quota
}
-// swagger:route GET /groupware/accounts/{account}/quota quota getquota
+// swagger:route GET /groupware/accounts/{account}/quota quota get_quota
// Get quota limits.
//
// responses:
@@ -30,10 +31,57 @@ func (g *Groupware) GetQuota(w http.ResponseWriter, r *http.Request) {
}
logger := log.From(req.logger.With().Str(logAccountId, accountId))
- res, sessionState, lang, jerr := g.jmap.GetQuotas(accountId, req.session, req.ctx, logger, req.language())
+ res, sessionState, lang, jerr := g.jmap.GetQuotas([]string{accountId}, req.session, req.ctx, logger, req.language())
if jerr != nil {
return req.errorResponseFromJmap(jerr)
}
- return etagResponse(res.List, sessionState, res.State, lang)
+ for _, v := range res {
+ return etagResponse(v.List, sessionState, v.State, lang)
+ }
+ return notFoundResponse(sessionState)
+ })
+}
+
+type AccountQuota struct {
+ Quotas []jmap.Quota `json:"quotas,omitempty"`
+ State jmap.State `json:"state"`
+}
+
+// When the request succeeds.
+// swagger:response GetQuotaForAllAccountsResponse200
+type SwaggerGetQuotaForAllAccountsResponse200 struct {
+ // in: body
+ Body map[string]AccountQuota
+}
+
+// swagger:route GET /groupware/accounts/all/quota quota get_quota_for_all_accounts
+// Get quota limits for all accounts.
+//
+// responses:
+//
+// 200: GetQuotaForAllAccountsResponse200
+// 400: ErrorResponse400
+// 500: ErrorResponse500
+func (g *Groupware) GetQuotaForAllAccounts(w http.ResponseWriter, r *http.Request) {
+ g.respond(w, r, func(req Request) Response {
+ accountIds := structs.Keys(req.session.Accounts)
+ if len(accountIds) < 1 {
+ return noContentResponse("")
+ }
+ logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
+
+ res, sessionState, lang, jerr := g.jmap.GetQuotas(accountIds, req.session, req.ctx, logger, req.language())
+ if jerr != nil {
+ return req.errorResponseFromJmap(jerr)
+ }
+
+ result := make(map[string]AccountQuota, len(res))
+ for accountId, accountQuotas := range res {
+ result[accountId] = AccountQuota{
+ State: accountQuotas.State,
+ Quotas: accountQuotas.List,
+ }
+ }
+ return response(result, sessionState, lang)
})
}
diff --git a/services/groupware/pkg/groupware/groupware_route.go b/services/groupware/pkg/groupware/groupware_route.go
index 70af31403..d2b3586ae 100644
--- a/services/groupware/pkg/groupware/groupware_route.go
+++ b/services/groupware/pkg/groupware/groupware_route.go
@@ -65,6 +65,7 @@ func (g *Groupware) Route(r chi.Router) {
r.Route("/emails", func(r chi.Router) {
r.Get("/latest/summary", g.GetLatestEmailsSummaryForAllAccounts)
})
+ r.Get("/quota", g.GetQuotaForAllAccounts)
})
r.Route("/accounts/{accountid}", func(r chi.Router) {
r.Get("/", g.GetAccount)