feat(mail): 重构邮箱权限体系并细化前台能力控制
- 新增邮箱前台权限与默认普通用户权限迁移,拆分读信、发信、草稿、定时、整理、标签、附件、联系人等能力。 - 收紧后端路由与处理逻辑,按权限限制邮箱前台、个人中心和定时发送相关接口。 - 前端根据权限动态隐藏或禁用邮件、个人中心中的对应功能入口与操作。 - 补充权限迁移与访问控制测试,覆盖普通用户邮箱前台、发信和定时发送的权限校验。
This commit is contained in:
@@ -170,6 +170,19 @@ func createTestMailbox(t *testing.T, admin *testClient, domainID, localPart, dis
|
||||
return mailbox
|
||||
}
|
||||
|
||||
func updateRegularPermissionGroup(t *testing.T, admin *testClient, permissions []string) PermissionGroup {
|
||||
t.Helper()
|
||||
var group PermissionGroup
|
||||
if code := admin.do("POST", "/api/admin/permission-groups/"+PermissionGroupRegular, map[string]any{
|
||||
"name": "Regular Users",
|
||||
"description": "Default permissions for regular users",
|
||||
"permissions": permissions,
|
||||
}, &group); code != http.StatusOK {
|
||||
t.Fatalf("update regular permission group code=%d group=%+v", code, group)
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
func systemSettingsPayload(settings SystemSettings) map[string]any {
|
||||
return map[string]any{
|
||||
"publicHostname": settings.PublicHostname,
|
||||
@@ -938,14 +951,7 @@ func TestFixedRolesProtectAdminRoutesAndDefaultAdmin(t *testing.T) {
|
||||
}, &errBody); code != http.StatusForbidden {
|
||||
t.Fatalf("system permission group update should be forbidden code=%d body=%v", code, errBody)
|
||||
}
|
||||
var regularGroup PermissionGroup
|
||||
if code := admin.do("POST", "/api/admin/permission-groups/"+PermissionGroupRegular, map[string]any{
|
||||
"name": "普通用户",
|
||||
"description": "Default permissions for regular users",
|
||||
"permissions": []string{PermissionAdminOverview},
|
||||
}, ®ularGroup); code != http.StatusOK {
|
||||
t.Fatalf("regular user group should be editable code=%d group=%+v", code, regularGroup)
|
||||
}
|
||||
regularGroup := updateRegularPermissionGroup(t, admin, []string{PermissionAdminOverview})
|
||||
if !regularGroup.System || !userHasPermission(&User{Role: "user", Permissions: regularGroup.Permissions}, PermissionAdminOverview) {
|
||||
t.Fatalf("regular group update did not persist permissions=%+v", regularGroup)
|
||||
}
|
||||
@@ -1205,6 +1211,75 @@ func TestLegacySystemPermissionGroupsAreCleanedUp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegularUserMailPermissionsAreEnforced(t *testing.T) {
|
||||
a := newTestApp(t)
|
||||
ts := httptest.NewServer(a.Router())
|
||||
defer ts.Close()
|
||||
admin := &testClient{t: t, server: ts}
|
||||
|
||||
var login map[string]any
|
||||
if code := admin.do("POST", "/api/auth/login", map[string]string{"email": "admin@lanqin.local", "password": "ChangeMe123!"}, &login); code != http.StatusOK {
|
||||
t.Fatalf("admin login code=%d body=%v", code, login)
|
||||
}
|
||||
mb := createTestMailbox(t, admin, mustDefaultDomainID(t, a), "front-perm", "Front Permissions", "Password123!", nil)
|
||||
|
||||
user := &testClient{t: t, server: ts}
|
||||
if code := user.do("POST", "/api/auth/login", map[string]string{"email": mb.Address, "password": "Password123!"}, &login); code != http.StatusOK {
|
||||
t.Fatalf("user login code=%d", code)
|
||||
}
|
||||
var mine struct {
|
||||
Items []Mailbox `json:"items"`
|
||||
}
|
||||
if code := user.do("GET", "/api/mail/mailboxes", nil, &mine); code != http.StatusOK || len(mine.Items) != 1 || mine.Items[0].ID != mb.ID {
|
||||
t.Fatalf("regular user should access mail front code=%d items=%+v", code, mine.Items)
|
||||
}
|
||||
var errBody map[string]any
|
||||
if code := user.do("GET", "/api/admin/overview", nil, &errBody); code != http.StatusForbidden {
|
||||
t.Fatalf("regular mail permissions should not grant admin access code=%d body=%v", code, errBody)
|
||||
}
|
||||
|
||||
updateRegularPermissionGroup(t, admin, withoutPermissions(regularUserDefaultPermissions(), PermissionMailAccess))
|
||||
noAccess := &testClient{t: t, server: ts}
|
||||
if code := noAccess.do("POST", "/api/auth/login", map[string]string{"email": mb.Address, "password": "Password123!"}, &login); code != http.StatusOK {
|
||||
t.Fatalf("no access login code=%d", code)
|
||||
}
|
||||
if code := noAccess.do("GET", "/api/mail/mailboxes", nil, &errBody); code != http.StatusForbidden {
|
||||
t.Fatalf("missing mail access should block mailbox list code=%d body=%v", code, errBody)
|
||||
}
|
||||
|
||||
updateRegularPermissionGroup(t, admin, withoutPermissions(regularUserDefaultPermissions(), PermissionMailSend))
|
||||
noSend := &testClient{t: t, server: ts}
|
||||
if code := noSend.do("POST", "/api/auth/login", map[string]string{"email": mb.Address, "password": "Password123!"}, &login); code != http.StatusOK {
|
||||
t.Fatalf("no send login code=%d", code)
|
||||
}
|
||||
sendPayload := map[string]any{
|
||||
"mailboxId": mb.ID,
|
||||
"to": []string{"someone@example.test"},
|
||||
"subject": "blocked send",
|
||||
"text": "body",
|
||||
"html": "<p>body</p>",
|
||||
}
|
||||
if code := noSend.do("POST", "/api/mail/send", sendPayload, &errBody); code != http.StatusForbidden {
|
||||
t.Fatalf("missing send permission should block send code=%d body=%v", code, errBody)
|
||||
}
|
||||
schedulePayload := map[string]any{
|
||||
"mailboxId": mb.ID,
|
||||
"to": []string{"someone@example.test"},
|
||||
"subject": "blocked schedule",
|
||||
"text": "body",
|
||||
"html": "<p>body</p>",
|
||||
"sendAt": time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339Nano),
|
||||
}
|
||||
if code := noSend.do("POST", "/api/mail/schedule-send", schedulePayload, &errBody); code != http.StatusForbidden {
|
||||
t.Fatalf("missing send permission should block scheduled send creation code=%d body=%v", code, errBody)
|
||||
}
|
||||
if code := noSend.do("GET", "/api/mail/scheduled-sends?mailboxId="+mb.ID, nil, &struct {
|
||||
Items []ScheduledSend `json:"items"`
|
||||
}{}); code != http.StatusOK {
|
||||
t.Fatalf("schedule management permission should remain usable code=%d", code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaildirSyncImportsRFC822(t *testing.T) {
|
||||
a := newTestApp(t)
|
||||
ctx := context.Background()
|
||||
@@ -1377,3 +1452,17 @@ func containsString(items []string, needle string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func withoutPermissions(items []string, removed ...string) []string {
|
||||
removedSet := map[string]bool{}
|
||||
for _, item := range removed {
|
||||
removedSet[item] = true
|
||||
}
|
||||
out := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
if !removedSet[item] {
|
||||
out = append(out, item)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ func (a *App) handleMailMessage(w http.ResponseWriter, r *http.Request) {
|
||||
respondError(w, http.StatusNotFound, "message not found")
|
||||
return
|
||||
}
|
||||
if r.URL.Query().Get("markRead") != "0" && !msg.IsRead {
|
||||
if r.URL.Query().Get("markRead") != "0" && !msg.IsRead && userHasPermission(currentUser(r), PermissionMailOrganize) {
|
||||
_, _ = a.db.ExecContext(r.Context(), `UPDATE messages SET is_read=1, updated_at=? WHERE id=?`, a.now().UTC().Format(time.RFC3339Nano), msg.ID)
|
||||
msg.IsRead = true
|
||||
}
|
||||
@@ -770,6 +770,11 @@ func (a *App) processScheduledSend(ctx context.Context, id, mailboxID, draftID,
|
||||
a.markScheduledSendFailed(ctx, id, "mailbox not found")
|
||||
return
|
||||
}
|
||||
user, err := a.userByID(ctx, mb.UserID)
|
||||
if err != nil || !userHasPermission(user, PermissionMailSchedule) || !userHasPermission(user, PermissionMailSend) {
|
||||
a.markScheduledSendFailed(ctx, id, "mail send permission revoked")
|
||||
return
|
||||
}
|
||||
compose := mailComposeInput{MailboxID: payload.MailboxID, To: payload.To, CC: payload.CC, BCC: payload.BCC, Subject: payload.Subject, Text: payload.Text, HTML: payload.HTML, Attachments: payload.Attachments}
|
||||
if _, err := a.sendMailNow(ctx, mb, compose); err != nil {
|
||||
a.markScheduledSendFailed(ctx, id, err.Error())
|
||||
|
||||
@@ -13,6 +13,23 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
PermissionMailAccess = "mail.access"
|
||||
|
||||
PermissionMailRead = "mail.messages.read"
|
||||
PermissionMailSend = "mail.messages.send"
|
||||
PermissionMailDrafts = "mail.messages.drafts"
|
||||
PermissionMailSchedule = "mail.messages.schedule"
|
||||
PermissionMailOrganize = "mail.messages.organize"
|
||||
PermissionMailLabels = "mail.labels.manage"
|
||||
PermissionMailAttachments = "mail.attachments.download"
|
||||
|
||||
PermissionMailContacts = "mail.contacts.manage"
|
||||
PermissionMailSignatures = "mail.signatures.manage"
|
||||
PermissionMailRules = "mail.rules.manage"
|
||||
PermissionMailBlocked = "mail.blocked_senders.manage"
|
||||
PermissionMailStats = "mail.stats.view"
|
||||
PermissionMailboxApply = "mail.mailboxes.apply"
|
||||
|
||||
PermissionAdminOverview = "admin.overview.view"
|
||||
|
||||
PermissionUsersView = "admin.users.view"
|
||||
@@ -65,6 +82,8 @@ const (
|
||||
PermissionSystemSettings = PermissionSettingsUpdate
|
||||
)
|
||||
|
||||
const regularUserPermissionMigrationKey = "permission_groups.regular_mail_permissions_v1"
|
||||
|
||||
const (
|
||||
PermissionGroupSuperAdmin = "pg_super_admin"
|
||||
PermissionGroupRegular = "pg_regular_user"
|
||||
@@ -117,6 +136,13 @@ type PermissionGroup struct {
|
||||
}
|
||||
|
||||
var legacyPermissionExpansions = map[string][]string{
|
||||
"mail": regularUserDefaultPermissions(),
|
||||
"mail.messages": {PermissionMailAccess, PermissionMailRead, PermissionMailSend, PermissionMailDrafts, PermissionMailSchedule, PermissionMailOrganize, PermissionMailAttachments},
|
||||
"mail.labels": {PermissionMailAccess, PermissionMailRead, PermissionMailLabels},
|
||||
"mail.contacts": {PermissionMailContacts},
|
||||
"mail.signatures": {PermissionMailSignatures},
|
||||
"mail.rules": {PermissionMailRules, PermissionMailBlocked},
|
||||
"mail.mailboxes": {PermissionMailboxApply},
|
||||
"admin.overview": {PermissionAdminOverview},
|
||||
"admin.users": {PermissionUsersView, PermissionUsersCreate, PermissionUsersUpdate, PermissionUsersDelete, PermissionUsersResetPassword, PermissionGroupsView},
|
||||
"admin.permission_groups": {PermissionGroupsView, PermissionGroupsCreate, PermissionGroupsUpdate, PermissionGroupsDelete},
|
||||
@@ -129,6 +155,21 @@ var legacyPermissionExpansions = map[string][]string{
|
||||
}
|
||||
|
||||
var permissionCatalogItems = []PermissionInfo{
|
||||
{Key: PermissionMailAccess, Label: "访问邮箱前台", Description: "进入邮箱前台并查看本人邮箱列表。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailRead, Label: "查看本人邮件", Description: "查看本人文件夹、邮件列表、星标邮件和邮件正文。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailSend, Label: "发送邮件", Description: "使用本人邮箱发送、回复和转发邮件。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailDrafts, Label: "管理草稿", Description: "保存、编辑和删除本人草稿。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailSchedule, Label: "定时发送", Description: "创建、查看和取消本人定时发送任务。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailOrganize, Label: "整理邮件", Description: "标记已读、星标、移动、归档、删除和清理本人邮件。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailLabels, Label: "管理邮件标签", Description: "创建标签,并为本人邮件添加或移除标签。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailAttachments, Label: "下载附件", Description: "下载本人邮件中的附件。", Category: "邮箱前台"},
|
||||
{Key: PermissionMailContacts, Label: "管理联系人", Description: "查看、新增和删除本人的联系人。", Category: "个人中心"},
|
||||
{Key: PermissionMailSignatures, Label: "管理签名", Description: "查看、新增、修改和删除本人的邮件签名。", Category: "个人中心"},
|
||||
{Key: PermissionMailRules, Label: "管理收件规则", Description: "查看、新增和删除本人的收件规则。", Category: "个人中心"},
|
||||
{Key: PermissionMailBlocked, Label: "管理拦截名单", Description: "查看、新增和删除本人的发件人拦截规则。", Category: "个人中心"},
|
||||
{Key: PermissionMailStats, Label: "查看邮箱统计", Description: "查看本人邮箱统计和清理概览。", Category: "个人中心"},
|
||||
{Key: PermissionMailboxApply, Label: "自助申请邮箱", Description: "在开放申请时为本人申请邮箱账号。", Category: "个人中心"},
|
||||
|
||||
{Key: PermissionAdminOverview, Label: "查看概览", Description: "查看后台统计和首次配置检查。", Category: "概览"},
|
||||
|
||||
{Key: PermissionUsersView, Label: "查看用户", Description: "查看用户列表、状态和绑定邮箱。", Category: "用户"},
|
||||
@@ -186,6 +227,16 @@ func allPermissionKeys() []string {
|
||||
return out
|
||||
}
|
||||
|
||||
func adminPermissionKeys() []string {
|
||||
out := make([]string, 0, len(permissionCatalogItems))
|
||||
for _, item := range permissionCatalogItems {
|
||||
if strings.HasPrefix(item.Key, "admin.") {
|
||||
out = append(out, item.Key)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func permissionSet() map[string]bool {
|
||||
out := map[string]bool{}
|
||||
for _, item := range permissionCatalogItems {
|
||||
@@ -269,12 +320,31 @@ func defaultPermissionGroups() []PermissionGroup {
|
||||
ID: PermissionGroupRegular,
|
||||
Name: "普通用户",
|
||||
Description: "仅可使用自己的邮箱功能,不包含后台权限。",
|
||||
Permissions: []string{},
|
||||
Permissions: regularUserDefaultPermissions(),
|
||||
System: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func regularUserDefaultPermissions() []string {
|
||||
return []string{
|
||||
PermissionMailAccess,
|
||||
PermissionMailRead,
|
||||
PermissionMailSend,
|
||||
PermissionMailDrafts,
|
||||
PermissionMailSchedule,
|
||||
PermissionMailOrganize,
|
||||
PermissionMailLabels,
|
||||
PermissionMailAttachments,
|
||||
PermissionMailContacts,
|
||||
PermissionMailSignatures,
|
||||
PermissionMailRules,
|
||||
PermissionMailBlocked,
|
||||
PermissionMailStats,
|
||||
PermissionMailboxApply,
|
||||
}
|
||||
}
|
||||
|
||||
func fixedPermissionGroupIDs() map[string]bool {
|
||||
out := map[string]bool{}
|
||||
for _, group := range defaultPermissionGroups() {
|
||||
@@ -331,9 +401,53 @@ func (a *App) ensureDefaultPermissionGroups(ctx context.Context) error {
|
||||
if err := a.cleanupLegacyDefaultPermissionGroups(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.ensureRegularUserMailPermissions(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) ensureRegularUserMailPermissions(ctx context.Context) error {
|
||||
var migrated string
|
||||
err := a.db.QueryRowContext(ctx, `SELECT value FROM system_settings WHERE key=?`, regularUserPermissionMigrationKey).Scan(&migrated)
|
||||
if err == nil && migrated == "1" {
|
||||
return nil
|
||||
}
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
var raw string
|
||||
if err := a.db.QueryRowContext(ctx, `SELECT permissions_json FROM permission_groups WHERE id=?`, PermissionGroupRegular).Scan(&raw); err != nil {
|
||||
return err
|
||||
}
|
||||
seen := map[string]bool{}
|
||||
for _, permission := range decodeStoredPermissions(raw) {
|
||||
seen[permission] = true
|
||||
}
|
||||
changed := false
|
||||
for _, permission := range regularUserDefaultPermissions() {
|
||||
if !seen[permission] {
|
||||
seen[permission] = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
now := a.now().UTC().Format(time.RFC3339Nano)
|
||||
if changed {
|
||||
permissions := make([]string, 0, len(seen))
|
||||
for _, permission := range allPermissionKeys() {
|
||||
if seen[permission] {
|
||||
permissions = append(permissions, permission)
|
||||
}
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `UPDATE permission_groups SET permissions_json=?, updated_at=? WHERE id=?`, encodePermissions(permissions), now, PermissionGroupRegular); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = a.db.ExecContext(ctx, `INSERT INTO system_settings(key,value,updated_at) VALUES(?,?,?)
|
||||
ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at`, regularUserPermissionMigrationKey, "1", now)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *App) cleanupLegacyDefaultPermissionGroups(ctx context.Context) error {
|
||||
for _, groupID := range legacyDefaultPermissionGroupIDs {
|
||||
var userCount int
|
||||
@@ -543,7 +657,7 @@ func userHasAnyPermission(user *User, permissions ...string) bool {
|
||||
}
|
||||
|
||||
func userHasAdminAccess(user *User) bool {
|
||||
return userHasAnyPermission(user, allPermissionKeys()...)
|
||||
return userHasAnyPermission(user, adminPermissionKeys()...)
|
||||
}
|
||||
|
||||
func (a *App) requireAdminAccess(next http.Handler) http.Handler {
|
||||
|
||||
@@ -36,53 +36,53 @@ func (a *App) Router() http.Handler {
|
||||
r.With(a.requireAuth).Get("/me", a.handleMe)
|
||||
r.With(a.requireAuth).Post("/me/profile", a.handleUpdateProfile)
|
||||
r.With(a.requireAuth).Post("/me/password", a.handleChangePassword)
|
||||
r.With(a.requireAuth).Get("/me/mailbox-apply-options", a.handleMailboxApplyOptions)
|
||||
r.With(a.requireAuth).Post("/me/mailboxes/apply", a.handleApplyMailbox)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailboxApply)).Get("/me/mailbox-apply-options", a.handleMailboxApplyOptions)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailboxApply)).Post("/me/mailboxes/apply", a.handleApplyMailbox)
|
||||
r.With(a.requireAuth).Post("/me/2fa/setup", a.handleTwoFactorSetup)
|
||||
r.With(a.requireAuth).Post("/me/2fa/enable", a.handleTwoFactorEnable)
|
||||
r.With(a.requireAuth).Post("/me/2fa/disable", a.handleTwoFactorDisable)
|
||||
r.With(a.requireAuth).Get("/me/contacts", a.handleListContacts)
|
||||
r.With(a.requireAuth).Post("/me/contacts", a.handleCreateContact)
|
||||
r.With(a.requireAuth).Delete("/me/contacts/{id}", a.handleDeleteContact)
|
||||
r.With(a.requireAuth).Get("/me/signatures", a.handleListSignatures)
|
||||
r.With(a.requireAuth).Post("/me/signatures", a.handleCreateSignature)
|
||||
r.With(a.requireAuth).Post("/me/signatures/{id}", a.handleUpdateSignature)
|
||||
r.With(a.requireAuth).Post("/me/signatures/{id}/default", a.handleSetDefaultSignature)
|
||||
r.With(a.requireAuth).Delete("/me/signatures/{id}", a.handleDeleteSignature)
|
||||
r.With(a.requireAuth).Get("/me/signatures/default", a.handleDefaultSignature)
|
||||
r.With(a.requireAuth).Get("/me/rules", a.handleListRules)
|
||||
r.With(a.requireAuth).Post("/me/rules", a.handleCreateRule)
|
||||
r.With(a.requireAuth).Delete("/me/rules/{id}", a.handleDeleteRule)
|
||||
r.With(a.requireAuth).Get("/me/blocked-senders", a.handleListBlockedSenders)
|
||||
r.With(a.requireAuth).Post("/me/blocked-senders", a.handleCreateBlockedSender)
|
||||
r.With(a.requireAuth).Delete("/me/blocked-senders/{id}", a.handleDeleteBlockedSender)
|
||||
r.With(a.requireAuth).Get("/me/stats", a.handleMailStats)
|
||||
r.With(a.requireAuth).Post("/me/cleanup", a.handleMailCleanup)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailContacts)).Get("/me/contacts", a.handleListContacts)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailContacts)).Post("/me/contacts", a.handleCreateContact)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailContacts)).Delete("/me/contacts/{id}", a.handleDeleteContact)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Get("/me/signatures", a.handleListSignatures)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Post("/me/signatures", a.handleCreateSignature)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Post("/me/signatures/{id}", a.handleUpdateSignature)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Post("/me/signatures/{id}/default", a.handleSetDefaultSignature)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Delete("/me/signatures/{id}", a.handleDeleteSignature)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailSignatures)).Get("/me/signatures/default", a.handleDefaultSignature)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailRules)).Get("/me/rules", a.handleListRules)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailRules)).Post("/me/rules", a.handleCreateRule)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailRules)).Delete("/me/rules/{id}", a.handleDeleteRule)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailBlocked)).Get("/me/blocked-senders", a.handleListBlockedSenders)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailBlocked)).Post("/me/blocked-senders", a.handleCreateBlockedSender)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailBlocked)).Delete("/me/blocked-senders/{id}", a.handleDeleteBlockedSender)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailStats)).Get("/me/stats", a.handleMailStats)
|
||||
r.With(a.requireAuth, a.requirePermission(PermissionMailOrganize)).Post("/me/cleanup", a.handleMailCleanup)
|
||||
r.With(a.requireAuth).Get("/events", a.handleEvents)
|
||||
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(a.requireAuth)
|
||||
r.Get("/mail/mailboxes", a.handleMyMailboxes)
|
||||
r.Get("/mail/folders", a.handleMailFolders)
|
||||
r.Get("/mail/labels", a.handleMailLabels)
|
||||
r.Post("/mail/labels", a.handleCreateMailLabel)
|
||||
r.Get("/mail/messages", a.handleMailMessages)
|
||||
r.Get("/mail/starred", a.handleStarredMessages)
|
||||
r.Get("/mail/messages/{id}", a.handleMailMessage)
|
||||
r.Post("/mail/send", a.handleMailSend)
|
||||
r.Get("/mail/scheduled-sends", a.handleScheduledSends)
|
||||
r.Post("/mail/schedule-send", a.handleScheduleSend)
|
||||
r.Delete("/mail/schedule-send/{id}", a.handleCancelScheduledSend)
|
||||
r.Post("/mail/drafts", a.handleSaveDraft)
|
||||
r.Post("/mail/drafts/{id}", a.handleSaveDraft)
|
||||
r.Delete("/mail/drafts/{id}", a.handleDeleteDraft)
|
||||
r.Post("/mail/messages/{id}/mark-read", a.handleMarkRead)
|
||||
r.Post("/mail/messages/{id}/star", a.handleStar)
|
||||
r.Post("/mail/messages/{id}/labels", a.handleAddMessageLabel)
|
||||
r.Delete("/mail/messages/{id}/labels/{labelID}", a.handleRemoveMessageLabel)
|
||||
r.Post("/mail/messages/{id}/move", a.handleMove)
|
||||
r.Delete("/mail/messages/{id}", a.handleDeleteMessage)
|
||||
r.Get("/mail/attachments/{id}", a.handleAttachment)
|
||||
r.With(a.requirePermission(PermissionMailAccess)).Get("/mail/mailboxes", a.handleMyMailboxes)
|
||||
r.With(a.requirePermission(PermissionMailRead)).Get("/mail/folders", a.handleMailFolders)
|
||||
r.With(a.requireAnyPermission(PermissionMailRead, PermissionMailLabels)).Get("/mail/labels", a.handleMailLabels)
|
||||
r.With(a.requirePermission(PermissionMailLabels)).Post("/mail/labels", a.handleCreateMailLabel)
|
||||
r.With(a.requirePermission(PermissionMailRead)).Get("/mail/messages", a.handleMailMessages)
|
||||
r.With(a.requirePermission(PermissionMailRead)).Get("/mail/starred", a.handleStarredMessages)
|
||||
r.With(a.requirePermission(PermissionMailRead)).Get("/mail/messages/{id}", a.handleMailMessage)
|
||||
r.With(a.requirePermission(PermissionMailSend)).Post("/mail/send", a.handleMailSend)
|
||||
r.With(a.requirePermission(PermissionMailSchedule)).Get("/mail/scheduled-sends", a.handleScheduledSends)
|
||||
r.With(a.requirePermission(PermissionMailSchedule), a.requirePermission(PermissionMailSend)).Post("/mail/schedule-send", a.handleScheduleSend)
|
||||
r.With(a.requirePermission(PermissionMailSchedule)).Delete("/mail/schedule-send/{id}", a.handleCancelScheduledSend)
|
||||
r.With(a.requirePermission(PermissionMailDrafts)).Post("/mail/drafts", a.handleSaveDraft)
|
||||
r.With(a.requirePermission(PermissionMailDrafts)).Post("/mail/drafts/{id}", a.handleSaveDraft)
|
||||
r.With(a.requirePermission(PermissionMailDrafts)).Delete("/mail/drafts/{id}", a.handleDeleteDraft)
|
||||
r.With(a.requirePermission(PermissionMailOrganize)).Post("/mail/messages/{id}/mark-read", a.handleMarkRead)
|
||||
r.With(a.requirePermission(PermissionMailOrganize)).Post("/mail/messages/{id}/star", a.handleStar)
|
||||
r.With(a.requirePermission(PermissionMailLabels)).Post("/mail/messages/{id}/labels", a.handleAddMessageLabel)
|
||||
r.With(a.requirePermission(PermissionMailLabels)).Delete("/mail/messages/{id}/labels/{labelID}", a.handleRemoveMessageLabel)
|
||||
r.With(a.requirePermission(PermissionMailOrganize)).Post("/mail/messages/{id}/move", a.handleMove)
|
||||
r.With(a.requirePermission(PermissionMailOrganize)).Delete("/mail/messages/{id}", a.handleDeleteMessage)
|
||||
r.With(a.requirePermission(PermissionMailAttachments)).Get("/mail/attachments/{id}", a.handleAttachment)
|
||||
})
|
||||
|
||||
r.Group(func(r chi.Router) {
|
||||
|
||||
Reference in New Issue
Block a user