Skip to content

Commit 17998fb

Browse files
committed
Refactor user auth models and permission checks.
- Move user models from `/models` to `internal/auth`. - Move and refactor various permission check functions into `User.()` - Refactor awkward `get, manage bool` function args into `Get|Manage` bitflags.
1 parent 5c78506 commit 17998fb

File tree

16 files changed

+288
-244
lines changed

16 files changed

+288
-244
lines changed

cmd/auth.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"github.com/knadh/listmonk/internal/auth"
1414
"github.com/knadh/listmonk/internal/utils"
15-
"github.com/knadh/listmonk/models"
1615
"github.com/labstack/echo/v4"
1716
"github.com/zerodha/simplesessions/v3"
1817
"gopkg.in/volatiletech/null.v6"
@@ -361,8 +360,8 @@ func doLoginSetup(c echo.Context) error {
361360
}
362361

363362
// Create the default "Super Admin".
364-
r := models.Role{
365-
Type: models.RoleTypeUser,
363+
r := auth.Role{
364+
Type: auth.RoleTypeUser,
366365
Name: null.NewString("Super Admin", true),
367366
}
368367
for p := range app.constants.Permissions {
@@ -374,16 +373,16 @@ func doLoginSetup(c echo.Context) error {
374373
}
375374

376375
// Create the super admin user.
377-
u := models.User{
378-
Type: models.UserTypeUser,
376+
u := auth.User{
377+
Type: auth.UserTypeUser,
379378
HasPassword: true,
380379
PasswordLogin: true,
381380
Username: username,
382381
Name: username,
383382
Password: null.NewString(password, true),
384383
Email: null.NewString(email, true),
385384
UserRoleID: role.ID,
386-
Status: models.UserStatusEnabled,
385+
Status: auth.UserStatusEnabled,
387386
}
388387
if _, err := app.core.CreateUser(u); err != nil {
389388
return err

cmd/campaigns.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var (
5454
func handleGetCampaigns(c echo.Context) error {
5555
var (
5656
app = c.Get("app").(*App)
57-
user = c.Get(auth.UserKey).(models.User)
57+
user = c.Get(auth.UserKey).(auth.User)
5858
pg = app.paginator.NewFromURL(c.Request().URL.Query())
5959

6060
status = c.QueryParams()["status"]
@@ -66,14 +66,14 @@ func handleGetCampaigns(c echo.Context) error {
6666
)
6767

6868
var (
69-
hasAllPerm = user.HasPerm(models.PermCampaignsGetAll)
69+
hasAllPerm = user.HasPerm(auth.PermCampaignsGetAll)
7070
permittedLists []int
7171
)
7272

7373
if !hasAllPerm {
7474
// Either the user has campaigns:get_all permissions and can view all campaigns,
7575
// or the campaigns are filtered by the lists the user has get|manage access to.
76-
hasAllPerm, permittedLists = user.GetPermittedLists(true, true)
76+
hasAllPerm, permittedLists = user.GetPermittedLists(auth.PermTypeGet | auth.PermTypeManage)
7777
}
7878

7979
// Query and retrieve the campaigns.
@@ -120,7 +120,7 @@ func handleGetCampaign(c echo.Context) error {
120120
}
121121

122122
// Check if the user has access to the campaign.
123-
if err := checkCampaignPerm(id, true, c); err != nil {
123+
if err := checkCampaignPerm(auth.PermTypeGet, id, c); err != nil {
124124
return err
125125
}
126126

@@ -151,7 +151,7 @@ func handlePreviewCampaign(c echo.Context) error {
151151
}
152152

153153
// Check if the user has access to the campaign.
154-
if err := checkCampaignPerm(id, true, c); err != nil {
154+
if err := checkCampaignPerm(auth.PermTypeGet, id, c); err != nil {
155155
return err
156156
}
157157

@@ -278,7 +278,7 @@ func handleUpdateCampaign(c echo.Context) error {
278278
}
279279

280280
// Check if the user has access to the campaign.
281-
if err := checkCampaignPerm(id, false, c); err != nil {
281+
if err := checkCampaignPerm(auth.PermTypeManage, id, c); err != nil {
282282
return err
283283
}
284284

@@ -326,7 +326,7 @@ func handleUpdateCampaignStatus(c echo.Context) error {
326326
}
327327

328328
// Check if the user has access to the campaign.
329-
if err := checkCampaignPerm(id, false, c); err != nil {
329+
if err := checkCampaignPerm(auth.PermTypeManage, id, c); err != nil {
330330
return err
331331
}
332332

@@ -359,7 +359,7 @@ func handleUpdateCampaignArchive(c echo.Context) error {
359359
)
360360

361361
// Check if the user has access to the campaign.
362-
if err := checkCampaignPerm(id, false, c); err != nil {
362+
if err := checkCampaignPerm(auth.PermTypeManage, id, c); err != nil {
363363
return err
364364
}
365365

@@ -401,7 +401,7 @@ func handleDeleteCampaign(c echo.Context) error {
401401
}
402402

403403
// Check if the user has access to the campaign.
404-
if err := checkCampaignPerm(id, false, c); err != nil {
404+
if err := checkCampaignPerm(auth.PermTypeManage, id, c); err != nil {
405405
return err
406406
}
407407

@@ -467,7 +467,7 @@ func handleTestCampaign(c echo.Context) error {
467467
}
468468

469469
// Check if the user has access to the campaign.
470-
if err := checkCampaignPerm(id, false, c); err != nil {
470+
if err := checkCampaignPerm(auth.PermTypeManage, id, c); err != nil {
471471
return err
472472
}
473473

@@ -707,32 +707,32 @@ func makeOptinCampaignMessage(o campaignReq, app *App) (campaignReq, error) {
707707
}
708708

709709
// checkCampaignPerm checks if the user has get or manage access to the given campaign.
710-
func checkCampaignPerm(id int, isGet bool, c echo.Context) error {
710+
func checkCampaignPerm(types auth.PermType, id int, c echo.Context) error {
711711
var (
712712
app = c.Get("app").(*App)
713-
user = c.Get(auth.UserKey).(models.User)
713+
user = c.Get(auth.UserKey).(auth.User)
714714
)
715715

716-
perm := models.PermCampaignsGet
717-
if isGet {
716+
perm := auth.PermCampaignsGet
717+
if types&auth.PermTypeGet != 0 {
718718
// It's a get request and there's a blanket get all permission.
719-
if user.HasPerm(models.PermCampaignsGetAll) {
719+
if user.HasPerm(auth.PermCampaignsGetAll) {
720720
return nil
721721
}
722722
} else {
723723
// It's a manage request and there's a blanket manage_all permission.
724-
if user.HasPerm(models.PermCampaignsManageAll) {
724+
if user.HasPerm(auth.PermCampaignsManageAll) {
725725
return nil
726726
}
727727

728-
perm = models.PermCampaignsManage
728+
perm = auth.PermCampaignsManage
729729
}
730730

731731
// There are no *_all campaign permissions. Instead, check if the user access
732732
// blanket get_all/manage_all list permissions. If yes, then the user can access
733733
// all campaigns. If there are no *_all permissions, then ensure that the
734734
// campaign belongs to the lists that the user has access to.
735-
if hasAllPerm, permittedListIDs := user.GetPermittedLists(true, true); !hasAllPerm {
735+
if hasAllPerm, permittedListIDs := user.GetPermittedLists(auth.PermTypeGet | auth.PermTypeManage); !hasAllPerm {
736736
if ok, err := app.core.CampaignHasLists(id, permittedListIDs); err != nil {
737737
return err
738738
} else if !ok {

cmd/init.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ func initAuth(db *sql.DB, ko *koanf.Koanf, co *core.Core) (bool, *auth.Auth) {
977977
c.SetCookie(cookie)
978978
return nil
979979
},
980-
GetUser: func(id int) (models.User, error) {
980+
GetUser: func(id int) (auth.User, error) {
981981
return co.GetUser(id, "", "")
982982
},
983983
}
@@ -1005,15 +1005,15 @@ func initAuth(db *sql.DB, ko *koanf.Koanf, co *core.Core) (bool, *auth.Auth) {
10051005
password = ko.String("app.admin_password")
10061006
)
10071007
if len(username) > 2 && len(password) > 6 {
1008-
u := models.User{
1008+
u := auth.User{
10091009
Username: username,
10101010
Password: null.String{Valid: true, String: password},
10111011
PasswordLogin: true,
10121012
HasPassword: true,
1013-
Status: models.UserStatusEnabled,
1014-
Type: models.UserTypeAPI,
1013+
Status: auth.UserStatusEnabled,
1014+
Type: auth.UserTypeAPI,
10151015
}
1016-
u.UserRole.ID = models.SuperAdminRoleID
1016+
u.UserRole.ID = auth.SuperAdminRoleID
10171017
a.CacheAPIUser(u)
10181018

10191019
lo.Println(`WARNING: Remove the admin_username and admin_password fields from the TOML configuration file. If you are using APIs, create and use new credentials. Users are now managed via the Admin -> Settings -> Users dashboard.`)

cmd/lists.go

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
func handleGetLists(c echo.Context) error {
1515
var (
1616
app = c.Get("app").(*App)
17-
user = c.Get(auth.UserKey).(models.User)
17+
user = c.Get(auth.UserKey).(auth.User)
1818
pg = app.paginator.NewFromURL(c.Request().URL.Query())
1919

2020
query = strings.TrimSpace(c.FormValue("query"))
@@ -29,7 +29,7 @@ func handleGetLists(c echo.Context) error {
2929
)
3030

3131
// Get the list IDs (or blanket permission) the user has access to.
32-
hasAllPerm, permittedIDs := user.GetPermittedLists(true, false)
32+
hasAllPerm, permittedIDs := user.GetPermittedLists(auth.PermTypeGet)
3333

3434
// Minimal query simply returns the list of all lists without JOIN subscriber counts. This is fast.
3535
if minimal {
@@ -69,7 +69,9 @@ func handleGetLists(c echo.Context) error {
6969
// It's permission checked by the listPerm middleware.
7070
func handleGetList(c echo.Context) error {
7171
var (
72-
app = c.Get("app").(*App)
72+
app = c.Get("app").(*App)
73+
user = c.Get(auth.UserKey).(auth.User)
74+
7375
id, _ = strconv.Atoi(c.Param("id"))
7476
)
7577

@@ -78,7 +80,7 @@ func handleGetList(c echo.Context) error {
7880
}
7981

8082
// Check if the user has access to the list.
81-
if err := checkListPerm(true, false, c, id); err != nil {
83+
if err := user.HasListPerm(auth.PermTypeGet, id); err != nil {
8284
return err
8385
}
8486

@@ -119,7 +121,9 @@ func handleCreateList(c echo.Context) error {
119121
// It's permission checked by the listPerm middleware.
120122
func handleUpdateList(c echo.Context) error {
121123
var (
122-
app = c.Get("app").(*App)
124+
app = c.Get("app").(*App)
125+
user = c.Get(auth.UserKey).(auth.User)
126+
123127
id, _ = strconv.Atoi(c.Param("id"))
124128
)
125129

@@ -128,7 +132,7 @@ func handleUpdateList(c echo.Context) error {
128132
}
129133

130134
// Check if the user has access to the list.
131-
if err := checkListPerm(false, true, c, id); err != nil {
135+
if err := user.HasListPerm(auth.PermTypeManage, id); err != nil {
132136
return err
133137
}
134138

@@ -155,7 +159,9 @@ func handleUpdateList(c echo.Context) error {
155159
// It's permission checked by the listPerm middleware.
156160
func handleDeleteLists(c echo.Context) error {
157161
var (
158-
app = c.Get("app").(*App)
162+
app = c.Get("app").(*App)
163+
user = c.Get(auth.UserKey).(auth.User)
164+
159165
id, _ = strconv.ParseInt(c.Param("id"), 10, 64)
160166
ids []int
161167
)
@@ -169,7 +175,7 @@ func handleDeleteLists(c echo.Context) error {
169175
}
170176

171177
// Check if the user has access to the list.
172-
if err := checkListPerm(true, false, c, ids...); err != nil {
178+
if err := user.HasListPerm(auth.PermTypeManage, ids...); err != nil {
173179
return err
174180
}
175181

@@ -180,35 +186,3 @@ func handleDeleteLists(c echo.Context) error {
180186

181187
return c.JSON(http.StatusOK, okResp{true})
182188
}
183-
184-
// checkListPerm checks if the user has get or manage access to the given list.
185-
func checkListPerm(get, manage bool, c echo.Context, listIDs ...int) error {
186-
var (
187-
app = c.Get("app").(*App)
188-
user = c.Get(auth.UserKey).(models.User)
189-
)
190-
191-
var permAll, perm string
192-
if get {
193-
permAll = models.PermListGetAll
194-
perm = models.PermListGet
195-
} else if manage {
196-
permAll = models.PermListManageAll
197-
perm = models.PermListManage
198-
}
199-
200-
// Check if the user has permissions for all lists or the specific list.
201-
if user.HasPerm(permAll) {
202-
return nil
203-
}
204-
205-
for _, id := range listIDs {
206-
if id > 0 {
207-
if user.HasListPerm(id, perm) {
208-
return nil
209-
}
210-
}
211-
}
212-
213-
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.permissionDenied", "name", "list"))
214-
}

cmd/roles.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"strconv"
77
"strings"
88

9-
"github.com/knadh/listmonk/models"
9+
"github.com/knadh/listmonk/internal/auth"
1010
"github.com/labstack/echo/v4"
1111
)
1212

@@ -44,7 +44,7 @@ func handleGeListRoles(c echo.Context) error {
4444
func handleCreateUserRole(c echo.Context) error {
4545
var (
4646
app = c.Get("app").(*App)
47-
r = models.Role{}
47+
r = auth.Role{}
4848
)
4949

5050
if err := c.Bind(&r); err != nil {
@@ -67,7 +67,7 @@ func handleCreateUserRole(c echo.Context) error {
6767
func handleCreateListRole(c echo.Context) error {
6868
var (
6969
app = c.Get("app").(*App)
70-
r = models.ListRole{}
70+
r = auth.ListRole{}
7171
)
7272

7373
if err := c.Bind(&r); err != nil {
@@ -98,7 +98,7 @@ func handleUpdateUserRole(c echo.Context) error {
9898
}
9999

100100
// Incoming params.
101-
var r models.Role
101+
var r auth.Role
102102
if err := c.Bind(&r); err != nil {
103103
return err
104104
}
@@ -135,7 +135,7 @@ func handleUpdateListRole(c echo.Context) error {
135135
}
136136

137137
// Incoming params.
138-
var r models.ListRole
138+
var r auth.ListRole
139139
if err := c.Bind(&r); err != nil {
140140
return err
141141
}
@@ -183,7 +183,7 @@ func handleDeleteRole(c echo.Context) error {
183183
return c.JSON(http.StatusOK, okResp{true})
184184
}
185185

186-
func validateUserRole(r models.Role, app *App) error {
186+
func validateUserRole(r auth.Role, app *App) error {
187187
// Validate fields.
188188
if !strHasLen(r.Name.String, 1, stdInputMaxLen) {
189189
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "name"))
@@ -198,7 +198,7 @@ func validateUserRole(r models.Role, app *App) error {
198198
return nil
199199
}
200200

201-
func validateListRole(r models.ListRole, app *App) error {
201+
func validateListRole(r auth.ListRole, app *App) error {
202202
// Validate fields.
203203
if !strHasLen(r.Name.String, 1, stdInputMaxLen) {
204204
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "name"))

0 commit comments

Comments
 (0)