Skip to content

Commit

Permalink
feat: add option to disable self-account editing
Browse files Browse the repository at this point in the history
  • Loading branch information
stonith404 committed Oct 28, 2024
1 parent 7bfc3f4 commit 8304065
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 30 deletions.
2 changes: 1 addition & 1 deletion backend/internal/bootstrap/router_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func initRouter(db *gorm.DB, appConfigService *service.AppConfigService) {
apiGroup := r.Group("/api")
controller.NewWebauthnController(apiGroup, jwtAuthMiddleware, middleware.NewRateLimitMiddleware(), webauthnService)
controller.NewOidcController(apiGroup, jwtAuthMiddleware, fileSizeLimitMiddleware, oidcService, jwtService)
controller.NewUserController(apiGroup, jwtAuthMiddleware, middleware.NewRateLimitMiddleware(), userService)
controller.NewUserController(apiGroup, jwtAuthMiddleware, middleware.NewRateLimitMiddleware(), userService, appConfigService)
controller.NewAppConfigController(apiGroup, jwtAuthMiddleware, appConfigService)
controller.NewAuditLogController(apiGroup, auditLogService, jwtAuthMiddleware)
controller.NewUserGroupController(apiGroup, jwtAuthMiddleware, userGroupService)
Expand Down
12 changes: 7 additions & 5 deletions backend/internal/common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ type ClientIdOrSecretNotProvidedError struct{}
func (e *ClientIdOrSecretNotProvidedError) Error() string {
return "Client id and secret not provided"
}

func (e *ClientIdOrSecretNotProvidedError) HttpStatusCode() int { return http.StatusBadRequest }

type WrongFileTypeError struct {
Expand All @@ -114,15 +113,13 @@ type WrongFileTypeError struct {
func (e *WrongFileTypeError) Error() string {
return fmt.Sprintf("File must be of type %s", e.ExpectedFileType)
}

func (e *WrongFileTypeError) HttpStatusCode() int { return http.StatusBadRequest }

type MissingSessionIdError struct{}

func (e *MissingSessionIdError) Error() string {
return "Missing session id"
}

func (e *MissingSessionIdError) HttpStatusCode() int { return http.StatusBadRequest }

type ReservedClaimError struct {
Expand All @@ -132,7 +129,6 @@ type ReservedClaimError struct {
func (e *ReservedClaimError) Error() string {
return fmt.Sprintf("Claim %s is reserved and can't be used", e.Key)
}

func (e *ReservedClaimError) HttpStatusCode() int { return http.StatusBadRequest }

type DuplicateClaimError struct {
Expand All @@ -142,5 +138,11 @@ type DuplicateClaimError struct {
func (e *DuplicateClaimError) Error() string {
return fmt.Sprintf("Claim %s is already defined", e.Key)
}

func (e *DuplicateClaimError) HttpStatusCode() int { return http.StatusBadRequest }

type AccountEditNotAllowedError struct{}

func (e *AccountEditNotAllowedError) Error() string {
return "You are not allowed to edit your account"
}
func (e *AccountEditNotAllowedError) HttpStatusCode() int { return http.StatusForbidden }
13 changes: 10 additions & 3 deletions backend/internal/controller/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controller

import (
"github.com/gin-gonic/gin"
"github.com/stonith404/pocket-id/backend/internal/common"
"github.com/stonith404/pocket-id/backend/internal/dto"
"github.com/stonith404/pocket-id/backend/internal/middleware"
"github.com/stonith404/pocket-id/backend/internal/service"
Expand All @@ -11,9 +12,10 @@ import (
"time"
)

func NewUserController(group *gin.RouterGroup, jwtAuthMiddleware *middleware.JwtAuthMiddleware, rateLimitMiddleware *middleware.RateLimitMiddleware, userService *service.UserService) {
func NewUserController(group *gin.RouterGroup, jwtAuthMiddleware *middleware.JwtAuthMiddleware, rateLimitMiddleware *middleware.RateLimitMiddleware, userService *service.UserService, appConfigService *service.AppConfigService) {
uc := UserController{
UserService: userService,
UserService: userService,
AppConfigService: appConfigService,
}

group.GET("/users", jwtAuthMiddleware.Add(true), uc.listUsersHandler)
Expand All @@ -30,7 +32,8 @@ func NewUserController(group *gin.RouterGroup, jwtAuthMiddleware *middleware.Jwt
}

type UserController struct {
UserService *service.UserService
UserService *service.UserService
AppConfigService *service.AppConfigService
}

func (uc *UserController) listUsersHandler(c *gin.Context) {
Expand Down Expand Up @@ -124,6 +127,10 @@ func (uc *UserController) updateUserHandler(c *gin.Context) {
}

func (uc *UserController) updateCurrentUserHandler(c *gin.Context) {
if uc.AppConfigService.DbConfig.AllowOwnAccountEdit.Value != "true" {
c.Error(&common.AccountEditNotAllowedError{})
return
}
uc.updateUser(c, true)
}

Expand Down
19 changes: 10 additions & 9 deletions backend/internal/dto/app_config_dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ type AppConfigVariableDto struct {
}

type AppConfigUpdateDto struct {
AppName string `json:"appName" binding:"required,min=1,max=30"`
SessionDuration string `json:"sessionDuration" binding:"required"`
EmailsVerified string `json:"emailsVerified" binding:"required"`
EmailEnabled string `json:"emailEnabled" binding:"required"`
SmtHost string `json:"smtpHost"`
SmtpPort string `json:"smtpPort"`
SmtpFrom string `json:"smtpFrom" binding:"omitempty,email"`
SmtpUser string `json:"smtpUser"`
SmtpPassword string `json:"smtpPassword"`
AppName string `json:"appName" binding:"required,min=1,max=30"`
SessionDuration string `json:"sessionDuration" binding:"required"`
EmailsVerified string `json:"emailsVerified" binding:"required"`
AllowOwnAccountEdit string `json:"allowOwnAccountEdit" binding:"required"`
EmailEnabled string `json:"emailEnabled" binding:"required"`
SmtHost string `json:"smtpHost"`
SmtpPort string `json:"smtpPort"`
SmtpFrom string `json:"smtpFrom" binding:"omitempty,email"`
SmtpUser string `json:"smtpUser"`
SmtpPassword string `json:"smtpPassword"`
}
6 changes: 4 additions & 2 deletions backend/internal/model/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ type AppConfigVariable struct {

type AppConfig struct {
AppName AppConfigVariable
SessionDuration AppConfigVariable
EmailsVerified AppConfigVariable
AllowOwnAccountEdit AppConfigVariable

BackgroundImageType AppConfigVariable
LogoLightImageType AppConfigVariable
LogoDarkImageType AppConfigVariable
SessionDuration AppConfigVariable
EmailsVerified AppConfigVariable

EmailEnabled AppConfigVariable
SmtpHost AppConfigVariable
Expand Down
6 changes: 6 additions & 0 deletions backend/internal/service/app_config_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ var defaultDbConfig = model.AppConfig{
Type: "bool",
DefaultValue: "false",
},
AllowOwnAccountEdit: model.AppConfigVariable{
Key: "allowOwnAccountEdit",
Type: "bool",
IsPublic: true,
DefaultValue: "true",
},
BackgroundImageType: model.AppConfigVariable{
Key: "backgroundImageType",
Type: "string",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/types/application-configuration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type AppConfig = {
appName: string;
allowOwnAccountEdit: boolean;
};

export type AllAppConfig = AppConfig & {
Expand Down
19 changes: 11 additions & 8 deletions frontend/src/routes/settings/account/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as Card from '$lib/components/ui/card';
import UserService from '$lib/services/user-service';
import WebAuthnService from '$lib/services/webauthn-service';
import appConfigStore from '$lib/stores/application-configuration-store';
import type { Passkey } from '$lib/types/passkey.type';
import type { UserCreate } from '$lib/types/user.type';
import { axiosErrorToast, getWebauthnErrorMessage } from '$lib/utils/error-util';
Expand Down Expand Up @@ -51,14 +52,16 @@
<title>Account Settings</title>
</svelte:head>

<Card.Root>
<Card.Header>
<Card.Title>Account Details</Card.Title>
</Card.Header>
<Card.Content>
<AccountForm {account} callback={updateAccount} />
</Card.Content>
</Card.Root>
{#if $appConfigStore.allowOwnAccountEdit}
<Card.Root>
<Card.Header>
<Card.Title>Account Details</Card.Title>
</Card.Header>
<Card.Content>
<AccountForm {account} callback={updateAccount} />
</Card.Content>
</Card.Root>
{/if}

<Card.Root>
<Card.Header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
const updatedAppConfig = {
appName: appConfig.appName,
sessionDuration: appConfig.sessionDuration,
emailsVerified: appConfig.emailsVerified
emailsVerified: appConfig.emailsVerified,
allowOwnAccountEdit: appConfig.allowOwnAccountEdit
};
const formSchema = z.object({
appName: z.string().min(2).max(30),
sessionDuration: z.number().min(1).max(43200),
emailsVerified: z.boolean()
emailsVerified: z.boolean(),
allowOwnAccountEdit: z.boolean()
});
const { inputs, ...form } = createForm<typeof formSchema>(formSchema, updatedAppConfig);
Expand All @@ -49,6 +51,17 @@
description="The duration of a session in minutes before the user has to sign in again."
bind:input={$inputs.sessionDuration}
/>
<div class="items-top mt-5 flex space-x-2">
<Checkbox id="admin-privileges" bind:checked={$inputs.allowOwnAccountEdit.value} />
<div class="grid gap-1.5 leading-none">
<Label for="admin-privileges" class="mb-0 text-sm font-medium leading-none">
Enable Self-Account Editing
</Label>
<p class="text-muted-foreground text-[0.8rem]">
Whether the user should be able to edit their own account details.
</p>
</div>
</div>
<div class="items-top mt-5 flex space-x-2">
<Checkbox id="admin-privileges" bind:checked={$inputs.emailsVerified.value} />
<div class="grid gap-1.5 leading-none">
Expand Down

0 comments on commit 8304065

Please sign in to comment.