From 475b932f9d0ec029ada844072e9d89bebd4e902c Mon Sep 17 00:00:00 2001
From: Elias Schneider
Date: Tue, 13 Aug 2024 20:51:10 +0200
Subject: [PATCH] feat: add option to change session duration
---
backend/internal/common/config.go | 5 +++
backend/internal/common/jwt.go | 4 +-
.../handler/application_configuration.go | 40 +++++++++++--------
.../model/application_configuration.go | 1 +
frontend/src/lib/components/form-input.svelte | 23 +++++++----
.../components/header/header-avatar.svelte | 7 ++--
.../application-configuration-service.ts | 12 +++---
.../lib/types/application-configuration.ts | 1 +
.../application-configuration/+page.server.ts | 2 +-
.../application-configuration-form.svelte | 26 +++++++++---
.../tests/application-configuration.spec.ts | 1 +
11 files changed, 79 insertions(+), 43 deletions(-)
diff --git a/backend/internal/common/config.go b/backend/internal/common/config.go
index d1262ac..6762e59 100644
--- a/backend/internal/common/config.go
+++ b/backend/internal/common/config.go
@@ -36,6 +36,11 @@ func NewDefaultDbConfig() model.ApplicationConfiguration {
IsPublic: true,
Value: "Pocket ID",
},
+ SessionDuration: model.ApplicationConfigurationVariable{
+ Key: "sessionDuration",
+ Type: "number",
+ Value: "60",
+ },
BackgroundImageType: model.ApplicationConfigurationVariable{
Key: "backgroundImageType",
Type: "string",
diff --git a/backend/internal/common/jwt.go b/backend/internal/common/jwt.go
index 41e4490..8a4586e 100644
--- a/backend/internal/common/jwt.go
+++ b/backend/internal/common/jwt.go
@@ -15,6 +15,7 @@ import (
"os"
"path/filepath"
"slices"
+ "strconv"
"strings"
"time"
)
@@ -73,10 +74,11 @@ func GenerateIDToken(user model.User, clientID string, scope string, nonce strin
// GenerateAccessToken generates an access token for the given user.
func GenerateAccessToken(user model.User) (tokenString string, err error) {
+ sessionDurationInMinutes, _ := strconv.Atoi(DbConfig.SessionDuration.Value)
claim := accessTokenJWTClaims{
RegisteredClaims: jwt.RegisteredClaims{
Subject: user.ID,
- ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(sessionDurationInMinutes) * time.Minute)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Audience: jwt.ClaimStrings{utils.GetHostFromURL(EnvConfig.AppURL)},
},
diff --git a/backend/internal/handler/application_configuration.go b/backend/internal/handler/application_configuration.go
index c952059..62a3efc 100644
--- a/backend/internal/handler/application_configuration.go
+++ b/backend/internal/handler/application_configuration.go
@@ -16,6 +16,7 @@ import (
func RegisterConfigurationRoutes(group *gin.RouterGroup) {
group.GET("/application-configuration", listApplicationConfigurationHandler)
+ group.GET("/application-configuration/all", middleware.JWTAuth(true), listAllApplicationConfigurationHandler)
group.PUT("/application-configuration", updateApplicationConfigurationHandler)
group.GET("/application-configuration/logo", getLogoHandler)
@@ -27,24 +28,11 @@ func RegisterConfigurationRoutes(group *gin.RouterGroup) {
}
func listApplicationConfigurationHandler(c *gin.Context) {
- // Return also the private configuration variables if the user is admin and showAll is true
- showAll := c.GetBool("userIsAdmin") && c.DefaultQuery("showAll", "false") == "true"
+ listApplicationConfiguration(c, false)
+}
- var configuration []model.ApplicationConfigurationVariable
- var err error
-
- if showAll {
- err = common.DB.Find(&configuration).Error
- } else {
- err = common.DB.Find(&configuration, "is_public = true").Error
- }
-
- if err != nil {
- utils.UnknownHandlerError(c, err)
- return
- }
-
- c.JSON(200, configuration)
+func listAllApplicationConfigurationHandler(c *gin.Context) {
+ listApplicationConfiguration(c, true)
}
func updateApplicationConfigurationHandler(c *gin.Context) {
@@ -188,3 +176,21 @@ func updateImage(c *gin.Context, imageName string, oldImageType string) {
c.Status(http.StatusNoContent)
}
+
+func listApplicationConfiguration(c *gin.Context, showAll bool) {
+ var configuration []model.ApplicationConfigurationVariable
+ var err error
+
+ if showAll {
+ err = common.DB.Find(&configuration).Error
+ } else {
+ err = common.DB.Find(&configuration, "is_public = true").Error
+ }
+
+ if err != nil {
+ utils.UnknownHandlerError(c, err)
+ return
+ }
+
+ c.JSON(200, configuration)
+}
diff --git a/backend/internal/model/application_configuration.go b/backend/internal/model/application_configuration.go
index fe244e7..b7a464d 100644
--- a/backend/internal/model/application_configuration.go
+++ b/backend/internal/model/application_configuration.go
@@ -12,6 +12,7 @@ type ApplicationConfiguration struct {
AppName ApplicationConfigurationVariable
BackgroundImageType ApplicationConfigurationVariable
LogoImageType ApplicationConfigurationVariable
+ SessionDuration ApplicationConfigurationVariable
}
type ApplicationConfigurationUpdateDto struct {
diff --git a/frontend/src/lib/components/form-input.svelte b/frontend/src/lib/components/form-input.svelte
index a285288..5424e01 100644
--- a/frontend/src/lib/components/form-input.svelte
+++ b/frontend/src/lib/components/form-input.svelte
@@ -7,10 +7,12 @@
let {
input = $bindable(),
label,
+ description,
children
}: {
input: FormInput;
label: string;
+ description?: string;
children?: Snippet;
} = $props();
@@ -18,13 +20,18 @@
-
- {#if children}
- {@render children()}
- {:else}
-
- {/if}
- {#if input.error}
-
{input.error}
+
+ {#if description}
+
{description}
{/if}
+
+ {#if children}
+ {@render children()}
+ {:else}
+
+ {/if}
+ {#if input.error}
+
{input.error}
+ {/if}
+
diff --git a/frontend/src/lib/components/header/header-avatar.svelte b/frontend/src/lib/components/header/header-avatar.svelte
index 11c55a1..d7ff792 100644
--- a/frontend/src/lib/components/header/header-avatar.svelte
+++ b/frontend/src/lib/components/header/header-avatar.svelte
@@ -1,5 +1,4 @@
@@ -31,7 +30,7 @@
{$userStore?.firstName}
{$userStore?.lastName}
- {$userStore?.email}
+ {$userStore?.email}
diff --git a/frontend/src/lib/services/application-configuration-service.ts b/frontend/src/lib/services/application-configuration-service.ts
index e517fe1..d384f8e 100644
--- a/frontend/src/lib/services/application-configuration-service.ts
+++ b/frontend/src/lib/services/application-configuration-service.ts
@@ -6,12 +6,12 @@ import APIService from './api-service';
export default class ApplicationConfigurationService extends APIService {
async list(showAll = false) {
- const { data } = await this.api.get(
- '/application-configuration',
- {
- params: { showAll }
- }
- );
+ let url = '/application-configuration';
+ if (showAll) {
+ url += '/all';
+ }
+
+ const { data } = await this.api.get(url);
const applicationConfiguration: Partial = {};
data.forEach(({ key, value }) => {
diff --git a/frontend/src/lib/types/application-configuration.ts b/frontend/src/lib/types/application-configuration.ts
index 3f56689..59cd45f 100644
--- a/frontend/src/lib/types/application-configuration.ts
+++ b/frontend/src/lib/types/application-configuration.ts
@@ -1,6 +1,7 @@
export type AllApplicationConfiguration = {
appName: string;
+ sessionDuration: string;
};
export type ApplicationConfiguration = AllApplicationConfiguration;
diff --git a/frontend/src/routes/settings/admin/application-configuration/+page.server.ts b/frontend/src/routes/settings/admin/application-configuration/+page.server.ts
index ab3c001..0c30081 100644
--- a/frontend/src/routes/settings/admin/application-configuration/+page.server.ts
+++ b/frontend/src/routes/settings/admin/application-configuration/+page.server.ts
@@ -5,6 +5,6 @@ export const load: PageServerLoad = async ({ cookies }) => {
const applicationConfigurationService = new ApplicationConfigurationService(
cookies.get('access_token')
);
- const applicationConfiguration = await applicationConfigurationService.list();
+ const applicationConfiguration = await applicationConfigurationService.list(true);
return { applicationConfiguration };
};
diff --git a/frontend/src/routes/settings/admin/application-configuration/application-configuration-form.svelte b/frontend/src/routes/settings/admin/application-configuration/application-configuration-form.svelte
index cb64ae7..2791b07 100644
--- a/frontend/src/routes/settings/admin/application-configuration/application-configuration-form.svelte
+++ b/frontend/src/routes/settings/admin/application-configuration/application-configuration-form.svelte
@@ -16,11 +16,21 @@
let isLoading = $state(false);
const updatedApplicationConfiguration: AllApplicationConfiguration = {
- appName: applicationConfiguration.appName
+ appName: applicationConfiguration.appName,
+ sessionDuration: applicationConfiguration.sessionDuration
};
const formSchema = z.object({
- appName: z.string().min(2).max(30)
+ appName: z.string().min(2).max(30),
+ sessionDuration: z.string().refine(
+ (val) => {
+ const num = Number(val);
+ return Number.isInteger(num) && num >= 1 && num <= 43200;
+ },
+ {
+ message: 'Session duration must be between 1 and 43200 minutes'
+ }
+ )
});
type FormSchema = typeof formSchema;
@@ -35,10 +45,14 @@