Skip to content

Commit

Permalink
Add api type user.
Browse files Browse the repository at this point in the history
  • Loading branch information
knadh committed Oct 13, 2024
1 parent bf0b500 commit 1516bf2
Show file tree
Hide file tree
Showing 17 changed files with 299 additions and 119 deletions.
85 changes: 59 additions & 26 deletions cmd/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ package main

import (
"net/http"
"regexp"
"strconv"
"strings"
"time"

"github.com/knadh/listmonk/internal/utils"
"github.com/knadh/listmonk/models"
"github.com/labstack/echo/v4"
"gopkg.in/volatiletech/null.v6"
)

var (
reUsername = regexp.MustCompile("^[a-zA-Z0-9_\\-\\.]+$")
)

// handleGetUsers retrieves users.
Expand Down Expand Up @@ -53,22 +60,33 @@ func handleCreateUser(c echo.Context) error {

u.Username = strings.TrimSpace(u.Username)
u.Name = strings.TrimSpace(u.Name)
u.Email = strings.TrimSpace(u.Email)

if u.Name == "" {
u.Name = u.Username
}
email := strings.TrimSpace(u.Email.String)

// Validate fields.
if !strHasLen(u.Username, 1, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "username"))
}

if u.PasswordLogin {
if !strHasLen(u.Password.String, 8, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
if !reUsername.MatchString(u.Username) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "username"))
}
if u.Type != models.UserTypeAPI {
if !utils.ValidateEmail(email) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "email"))
}
if u.PasswordLogin {
if !strHasLen(u.Password.String, 8, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
}
}

u.Email = null.String{String: email, Valid: true}
}

if u.Name == "" {
u.Name = u.Username
}

// Create the user in the database.
out, err := app.core.CreateUser(u)
if err != nil {
return err
Expand Down Expand Up @@ -97,34 +115,49 @@ func handleUpdateUser(c echo.Context) error {
// Validate.
u.Username = strings.TrimSpace(u.Username)
u.Name = strings.TrimSpace(u.Name)
u.Email = strings.TrimSpace(u.Email)

if u.Name == "" {
u.Name = u.Username
}
email := strings.TrimSpace(u.Email.String)

// Validate fields.
if !strHasLen(u.Username, 1, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "username"))
}
if !reUsername.MatchString(u.Username) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "username"))
}

if u.PasswordLogin {
if u.Password.String != "" {
if u.Type != models.UserTypeAPI {
if !utils.ValidateEmail(email) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "email"))
}
if u.PasswordLogin && u.Password.String != "" {
if !strHasLen(u.Password.String, 8, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
}
} else {
// Get the existing user for password validation.
user, err := app.core.GetUser(id)
if err != nil {
return err
}

// If password login is enabled, but there's no password in the DB and there's no incoming
// password, throw an error.
if !user.HasPassword {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
if u.Password.String != "" {
if !strHasLen(u.Password.String, 8, stdInputMaxLen) {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
}
} else {
// Get the existing user for password validation.
user, err := app.core.GetUser(id)
if err != nil {
return err
}

// If password login is enabled, but there's no password in the DB and there's no incoming
// password, throw an error.
if !user.HasPassword {
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("globals.messages.invalidFields", "name", "password"))
}
}
}

u.Email = null.String{String: email, Valid: true}
}

if u.Name == "" {
u.Name = u.Username
}

out, err := app.core.UpdateUser(id, u)
Expand Down
28 changes: 14 additions & 14 deletions frontend/fontello/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,20 @@
"code": 59431,
"src": "typicons"
},
{
"uid": "77025195d19e048302e8943e2da4cc75",
"css": "account-outline",
"code": 983059,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M500 166Q568.4 166 617.2 214.8T666 333 617.2 451.2 500 500 382.8 451.2 334 333 382.8 214.8 500 166ZM500 250Q464.8 250 440.4 274.4T416 333 440.4 391.6 500 416 559.6 391.6 584 333 559.6 274.4 500 250ZM500 541Q562.5 541 636.7 560.5 720.7 582 771.5 615.2 834 656.3 834 709V834H166V709Q166 656.3 228.5 615.2 279.3 582 363.3 560.5 437.5 541 500 541ZM500 621.1Q441.4 621.1 378.9 636.7 324.2 652.3 285.2 673.8T246.1 709V753.9H753.9V709Q753.9 695.3 714.8 673.8T621.1 636.7Q558.6 621.1 500 621.1Z",
"width": 1000
},
"search": [
"account-outline"
]
},
{
"uid": "f4ad3f6d071a0bfb3a8452b514ed0892",
"css": "vector-square",
Expand Down Expand Up @@ -838,20 +852,6 @@
"account-off"
]
},
{
"uid": "77025195d19e048302e8943e2da4cc75",
"css": "account-outline",
"code": 983059,
"src": "custom_icons",
"selected": false,
"svg": {
"path": "M500 166Q568.4 166 617.2 214.8T666 333 617.2 451.2 500 500 382.8 451.2 334 333 382.8 214.8 500 166ZM500 250Q464.8 250 440.4 274.4T416 333 440.4 391.6 500 416 559.6 391.6 584 333 559.6 274.4 500 250ZM500 541Q562.5 541 636.7 560.5 720.7 582 771.5 615.2 834 656.3 834 709V834H166V709Q166 656.3 228.5 615.2 279.3 582 363.3 560.5 437.5 541 500 541ZM500 621.1Q441.4 621.1 378.9 636.7 324.2 652.3 285.2 673.8T246.1 709V753.9H753.9V709Q753.9 695.3 714.8 673.8T621.1 636.7Q558.6 621.1 500 621.1Z",
"width": 1000
},
"search": [
"account-outline"
]
},
{
"uid": "571120b7ff63feb71df85710d019302c",
"css": "account-plus",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/assets/icons/fontello.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}


.mdi-view-dashboard-variant-outline:before { content: '\e800'; } /* '' */
.mdi-format-list-bulleted-square:before { content: '\e801'; } /* '' */
.mdi-newspaper-variant-outline:before { content: '\e802'; } /* '' */
Expand Down Expand Up @@ -115,6 +116,7 @@
.mdi-email-bounce:before { content: '\e825'; } /* '' */
.mdi-speedometer:before { content: '\e826'; } /* '' */
.mdi-warning-empty:before { content: '\e827'; } /* '' */
.mdi-account-outline:before { content: '󰀓'; } /* '\f0013' */
.mdi-code:before { content: '󰅩'; } /* '\f0169' */
.mdi-logout-variant:before { content: '󰗽'; } /* '\f05fd' */
.mdi-wrench-outline:before { content: '󰯠'; } /* '\f0be0' */
Binary file modified frontend/src/assets/icons/fontello.woff2
Binary file not shown.
15 changes: 12 additions & 3 deletions frontend/src/assets/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -563,21 +563,21 @@ body.is-noscroll {
color: $grey;
}

&.private, &.scheduled, &.paused, &.tx {
&.private, &.scheduled, &.paused, &.tx, &.api {
$color: #ed7b00;
color: $color;
background: #fff7e6;
border: 1px solid lighten($color, 37%);
box-shadow: 1px 1px 0 lighten($color, 37%);
}
&.public, &.running, &.list, &.campaign, &.super {
&.public, &.running, &.list, &.campaign, &.user {
$color: $primary;
color: lighten($color, 20%);;
background: #e6f7ff;
border: 1px solid lighten($color, 42%);
box-shadow: 1px 1px 0 lighten($color, 42%);
}
&.finished, &.enabled, &.status-confirmed {
&.finished, &.enabled, &.status-confirmed, &.super {
$color: $green;
color: $color;
background: #f6ffed;
Expand Down Expand Up @@ -897,6 +897,15 @@ section.users {
min-width: 100px !important;
}
}
.user-api-token .copy-text {
background: rgba($green, .1);
display: block;
width: 100%;
border-radius: 3px;
padding: 15px;
font-size: 1.2rem;
color: $green;
}


/* C3 charting lib */
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/views/SubscriberForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
<div class="column is-4">
<b-field :label="$t('globals.fields.status')" label-position="on-border"
:message="$t('subscribers.blocklistedHelp')">
<b-select v-model="form.status" name="status" :placeholder="$t('globals.fields.status')" required expanded>
<b-select v-model="form.status" name="status" :placeholder="$t('globals.fields.status')" required
expanded>
<option value="enabled">
{{ $t('subscribers.status.enabled') }}
</option>
Expand Down
Loading

0 comments on commit 1516bf2

Please sign in to comment.