mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-05-12 16:09:53 +00:00
Merge branch 'main' into feat/add_form_post
This commit is contained in:
@@ -164,7 +164,7 @@ require (
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect
|
||||
google.golang.org/grpc v1.79.1 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.68.0 // indirect
|
||||
|
||||
@@ -470,8 +470,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d h1:
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:48U2I+QQUYhsFrg2SY6r+nJzeOtjey7j//WBESw+qyQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
|
||||
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/pocket-id/pocket-id/backend/internal/storage"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/utils"
|
||||
@@ -20,6 +21,8 @@ import (
|
||||
|
||||
// initApplicationImages copies the images from the embedded directory to the storage backend
|
||||
// and returns a map containing the detected file extensions in the application-images directory.
|
||||
//
|
||||
//nolint:gocognit
|
||||
func initApplicationImages(ctx context.Context, fileStorage storage.FileStorage) (map[string]string, error) {
|
||||
// Previous versions of images
|
||||
// If these are found, they are deleted
|
||||
@@ -76,6 +79,18 @@ func initApplicationImages(ctx context.Context, fileStorage storage.FileStorage)
|
||||
dstNameToExt[nameWithoutExt] = ext
|
||||
}
|
||||
|
||||
initedPath := path.Join("application-images", ".inited")
|
||||
if _, _, err := fileStorage.Open(ctx, initedPath); err == nil {
|
||||
return dstNameToExt, nil
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("failed to read .inited: %w", err)
|
||||
} else {
|
||||
err := fileStorage.Save(ctx, initedPath, strings.NewReader(""))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to store .inited: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy images from the images directory to the application-images directory if they don't already exist
|
||||
for _, sourceFile := range sourceFiles {
|
||||
if sourceFile.IsDir() {
|
||||
|
||||
@@ -49,6 +49,10 @@ func initRouter(db *gorm.DB, svc *services) (utils.Service, error) {
|
||||
_ = r.SetTrustedProxies(nil)
|
||||
}
|
||||
|
||||
if common.EnvConfig.TrustedPlatform != "" {
|
||||
r.TrustedPlatform = common.EnvConfig.TrustedPlatform
|
||||
}
|
||||
|
||||
if common.EnvConfig.TracingEnabled {
|
||||
r.Use(otelgin.Middleware(common.Name))
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ type EnvConfigSchema struct {
|
||||
DbProvider DbProvider
|
||||
DbConnectionString string `env:"DB_CONNECTION_STRING" options:"file"`
|
||||
TrustProxy bool `env:"TRUST_PROXY"`
|
||||
TrustedPlatform string `env:"TRUSTED_PLATFORM"`
|
||||
AuditLogRetentionDays int `env:"AUDIT_LOG_RETENTION_DAYS"`
|
||||
AnalyticsDisabled bool `env:"ANALYTICS_DISABLED"`
|
||||
AllowDowngrade bool `env:"ALLOW_DOWNGRADE"`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dto
|
||||
|
||||
type SignUpDto struct {
|
||||
Username string `json:"username" binding:"required,username,min=2,max=50" unorm:"nfc"`
|
||||
Username string `json:"username" binding:"required,username,min=1,max=50" unorm:"nfc"`
|
||||
Email *string `json:"email" binding:"omitempty,email" unorm:"nfc"`
|
||||
FirstName string `json:"firstName" binding:"max=50" unorm:"nfc"`
|
||||
LastName string `json:"lastName" binding:"max=50" unorm:"nfc"`
|
||||
|
||||
@@ -23,7 +23,7 @@ type UserDto struct {
|
||||
}
|
||||
|
||||
type UserCreateDto struct {
|
||||
Username string `json:"username" binding:"required,username,min=2,max=50" unorm:"nfc"`
|
||||
Username string `json:"username" binding:"required,username,min=1,max=50" unorm:"nfc"`
|
||||
Email *string `json:"email" binding:"omitempty,email" unorm:"nfc"`
|
||||
EmailVerified bool `json:"emailVerified"`
|
||||
FirstName string `json:"firstName" binding:"max=50" unorm:"nfc"`
|
||||
|
||||
@@ -13,7 +13,8 @@ import (
|
||||
// [a-zA-Z0-9] : The username must start with an alphanumeric character
|
||||
// [a-zA-Z0-9_.@-]* : The rest of the username can contain alphanumeric characters, dots, underscores, hyphens, and "@" symbols
|
||||
// [a-zA-Z0-9]$ : The username must end with an alphanumeric character
|
||||
var validateUsernameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.@-]*[a-zA-Z0-9]$")
|
||||
// (...)? : This allows single-character usernames (just one alphanumeric character)
|
||||
var validateUsernameRegex = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9_.@-]*[a-zA-Z0-9])?$")
|
||||
|
||||
var validateClientIDRegex = regexp.MustCompile("^[a-zA-Z0-9._-]+$")
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ func TestValidateUsername(t *testing.T) {
|
||||
{"starts with symbol", ".username", false},
|
||||
{"ends with non-alphanumeric", "username-", false},
|
||||
{"contains space", "user name", false},
|
||||
{"valid single char", "a", true},
|
||||
{"empty", "", false},
|
||||
{"only special chars", "-._@", false},
|
||||
{"valid long", "a1234567890_b.c-d@e", true},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,7 +102,7 @@
|
||||
"see_your_recent_account_activities": "See your account activities within the configured retention period.",
|
||||
"time": "Time",
|
||||
"event": "Event",
|
||||
"approximate_location": "Approximate Location",
|
||||
"approximate_location": "Omtrentlig plassering",
|
||||
"ip_address": "IP adresse",
|
||||
"device": "Enhet",
|
||||
"client": "Klient",
|
||||
|
||||
@@ -31,7 +31,7 @@ export const callbackUrlSchema = z
|
||||
|
||||
export const usernameSchema = z
|
||||
.string()
|
||||
.min(2)
|
||||
.min(1)
|
||||
.max(30)
|
||||
.regex(/^[a-zA-Z0-9]/, m.username_must_start_with())
|
||||
.regex(/[a-zA-Z0-9]$/, m.username_must_end_with())
|
||||
|
||||
@@ -66,7 +66,7 @@ test('Change Locale', async ({ page }) => {
|
||||
// Check if the validation messages are translated because they are provided by Zod
|
||||
await page.getByRole('textbox', { name: 'Gebruikersnaam' }).fill('');
|
||||
await page.getByRole('button', { name: 'Opslaan' }).click();
|
||||
await expect(page.getByText('Te kort: verwacht dat string >=2 tekens heeft')).toBeVisible();
|
||||
await expect(page.getByText('Te kort: verwacht dat string >=1 tekens heeft')).toBeVisible();
|
||||
|
||||
// Clear all cookies and sign in again to check if the language is still set to Dutch
|
||||
await page.context().clearCookies();
|
||||
@@ -76,7 +76,7 @@ test('Change Locale', async ({ page }) => {
|
||||
|
||||
await page.getByRole('textbox', { name: 'Gebruikersnaam' }).fill('');
|
||||
await page.getByRole('button', { name: 'Opslaan' }).click();
|
||||
await expect(page.getByText('Te kort: verwacht dat string >=2 tekens heeft')).toBeVisible();
|
||||
await expect(page.getByText('Te kort: verwacht dat string >=1 tekens heeft')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Add passkey to an account', async ({ page }) => {
|
||||
|
||||
@@ -109,7 +109,7 @@ function compareExports(dir1: string, dir2: string): void {
|
||||
const hashes2 = hashAllFiles(dir2);
|
||||
|
||||
const files1 = Object.keys(hashes1).sort();
|
||||
const files2 = Object.keys(hashes2).sort();
|
||||
const files2 = Object.keys(hashes2).sort().filter(p => !p.includes('.inited'));
|
||||
expect(files2).toEqual(files1);
|
||||
|
||||
for (const file of files1) {
|
||||
|
||||
Reference in New Issue
Block a user