diff --git a/backend/config/config.go b/backend/config/config.go
index 2184ea2..56f62ba 100644
--- a/backend/config/config.go
+++ b/backend/config/config.go
@@ -26,7 +26,7 @@ import (
type Config struct {
Hostname string `mapstructure:"HOSTNAME"`
- Port string `mapstructure:"PORT"`
+ Port uint16 `mapstructure:"PORT"`
DatabaseUrl string `mapstructure:"POSTGRES_URL"`
RedisUrl string `mapstructure:"REDIS_URL"`
@@ -39,6 +39,16 @@ type Config struct {
JwtExpAccess int `mapstructure:"JWT_EXP_ACCESS"`
JwtExpRefresh int `mapstructure:"JWT_EXP_REFRESH"`
+ SmtpEnabled bool `mapstructure:"SMTP_ENABLED"`
+ SmtpServer string `mapstructure:"SMTP_SERVER"`
+ SmtpPort uint16 `mapstructure:"SMTP_PORT"`
+ SmtpUser string `mapstructure:"SMTP_USER"`
+ SmtpPassword string `mapstructure:"SMTP_PASSWORD"`
+ SmtpFrom string `mapstructure:"SMTP_FROM"`
+ SmtpUseTLS bool `mapstructure:"SMTP_USE_TLS"`
+ SmtpUseSSL bool `mapstructure:"SMTP_USE_SSL"`
+ SmtpTimeout uint `mapstructure:"SMTP_TIMEOUT"`
+
PasswordMinLength int `mapstructure:"PASSWORD_MIN_LENGTH"`
PasswordMaxLength int `mapstructure:"PASSWORD_MIN_LENGTH"`
PasswordCheckNumbers bool `mapstructure:"PASSWORD_CHECK_NUMBERS"`
@@ -47,7 +57,7 @@ type Config struct {
PasswordCheckSymbols bool `mapstructure:"PASSWORD_CHECK_SYMBOLS"`
PasswordCheckLeaked bool `mapstructure:"PASSWORD_CHECK_LEAKED"`
- Environment string `mapstructure:"ENVIRONMENT"`
+ Environment string `mapstructure:"ENVIRONMENT"`
}
func Load() (*Config, error) {
@@ -62,6 +72,11 @@ func Load() (*Config, error) {
viper.SetDefault("JWT_AUDIENCE", "easywish")
viper.SetDefault("JWT_ISSUER", "easywish")
+ viper.SetDefault("SMTP_ENABLED", false)
+ viper.SetDefault("SMTP_USE_TLS", false)
+ viper.SetDefault("SMTP_USE_SSL", false)
+ viper.SetDefault("SMTP_FROM", "An Easywish instance")
+
viper.SetDefault("PASSWORD_MIN_LENGTH", 6)
viper.SetDefault("PASSWORD_MAX_LENGTH", 100)
viper.SetDefault("PASSWORD_CHECK_NUMBERS", false)
@@ -93,6 +108,16 @@ func Load() (*Config, error) {
viper.BindEnv("JWT_EXP_ACCESS")
viper.BindEnv("JWT_EXP_REFRESH")
+ viper.BindEnv("SMTP_ENABLED")
+ viper.BindEnv("SMTP_SERVER")
+ viper.BindEnv("SMTP_PORT")
+ viper.BindEnv("SMTP_USER")
+ viper.BindEnv("SMTP_PASSWORD")
+ viper.BindEnv("SMTP_FROM")
+ viper.BindEnv("SMTP_USE_TLS")
+ viper.BindEnv("SMTP_USE_SSL")
+ viper.BindEnv("SMTP_TIMEOUT")
+
viper.BindEnv("PASSWORD_MIN_LENGTH")
viper.BindEnv("PASSWORD_MAX_LENGTH")
viper.BindEnv("PASSWORD_CHECK_NUMBERS")
diff --git a/backend/internal/errors/postgres.go b/backend/internal/errors/postgres.go
index 79abeca..a58151c 100644
--- a/backend/internal/errors/postgres.go
+++ b/backend/internal/errors/postgres.go
@@ -1,3 +1,20 @@
+// Copyright (c) 2025 Nikolai Papin
+//
+// This file is part of Easywish
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+// the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
package errors
import (
diff --git a/backend/internal/services/smtp.go b/backend/internal/services/smtp.go
new file mode 100644
index 0000000..f56b2f7
--- /dev/null
+++ b/backend/internal/services/smtp.go
@@ -0,0 +1,18 @@
+// Copyright (c) 2025 Nikolai Papin
+//
+// This file is part of Easywish
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+// the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package services
diff --git a/backend/internal/utils/pointer.go b/backend/internal/utils/pointer.go
index c6cd178..1a3b459 100644
--- a/backend/internal/utils/pointer.go
+++ b/backend/internal/utils/pointer.go
@@ -1,3 +1,20 @@
+// Copyright (c) 2025 Nikolai Papin
+//
+// This file is part of Easywish
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+// the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
package utils
func NewPointer[T any](d T) *T {
diff --git a/sqlc/query.sql b/sqlc/query.sql
index c043b27..e15eb78 100644
--- a/sqlc/query.sql
+++ b/sqlc/query.sql
@@ -1,5 +1,22 @@
-- vim:fileencoding=utf-8:foldmethod=marker
+-- Copyright (c) 2025 Nikolai Papin
+--
+-- This file is part of Easywish
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+-- the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+
--: User Object {{{
;-- name: CreateUser :one
@@ -163,6 +180,12 @@ WHERE id = $1;
SELECT * FROM sessions
WHERE user_id = $1 AND terminated IS FALSE;
+;-- name: TerminateAllSessionsForUserByUsername :exec
+UPDATE sessions
+SET terminated = TRUE
+FROM users
+WHERE sessions.user_id = users.id AND users.username = @username::text;
+
;-- name: PruneTerminatedSessions :exec
DELETE FROM sessions
WHERE terminated IS TRUE;
diff --git a/sqlc/schema.sql b/sqlc/schema.sql
index 3e6c2df..cb9b186 100644
--- a/sqlc/schema.sql
+++ b/sqlc/schema.sql
@@ -1,3 +1,22 @@
+-- Copyright (c) 2025 Nikolai Papin
+--
+-- This file is part of Easywish
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+-- the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+
+;
+
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE IF NOT EXISTS "users" (