Compare commits
5 Commits
0aa332c26b
...
82413499f5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82413499f5 | ||
|
|
df82782ba5 | ||
|
|
b42713b108 | ||
|
|
0d7c5674da | ||
|
|
46e09a1285 |
@@ -9,8 +9,7 @@
|
|||||||
"Host": "mail.server.com",
|
"Host": "mail.server.com",
|
||||||
"User": "username",
|
"User": "username",
|
||||||
"Password": "password",
|
"Password": "password",
|
||||||
"Port": 465,
|
"Port": 465
|
||||||
"AdminEmail": "admin@server.com"
|
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
"MailPath": "templates/email",
|
"MailPath": "templates/email",
|
||||||
@@ -23,7 +22,8 @@
|
|||||||
},
|
},
|
||||||
"recipients": {
|
"recipients": {
|
||||||
"ContactForm": "contacts@server.com",
|
"ContactForm": "contacts@server.com",
|
||||||
"UserRegistration": "registration@server.com"
|
"UserRegistration": "registration@server.com",
|
||||||
|
"AdminEmail": "admin@server.com"
|
||||||
},
|
},
|
||||||
"security": {
|
"security": {
|
||||||
"RateLimits": {
|
"RateLimits": {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ type SMTPConfig struct {
|
|||||||
Host string `json:"Host" envconfig:"SMTP_HOST"`
|
Host string `json:"Host" envconfig:"SMTP_HOST"`
|
||||||
User string `json:"User" envconfig:"SMTP_USER"`
|
User string `json:"User" envconfig:"SMTP_USER"`
|
||||||
Password string `json:"Password" envconfig:"SMTP_PASS"`
|
Password string `json:"Password" envconfig:"SMTP_PASS"`
|
||||||
AdminEmail string `json:"AdminEmail" envconfig:"ADMIN_MAIL"`
|
|
||||||
Port int `json:"Port" default:"465" envconfig:"SMTP_PORT"`
|
Port int `json:"Port" default:"465" envconfig:"SMTP_PORT"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +46,7 @@ type TemplateConfig struct {
|
|||||||
type RecipientsConfig struct {
|
type RecipientsConfig struct {
|
||||||
ContactForm string `json:"ContactForm" envconfig:"RECIPIENT_CONTACT_FORM"`
|
ContactForm string `json:"ContactForm" envconfig:"RECIPIENT_CONTACT_FORM"`
|
||||||
UserRegistration string `json:"UserRegistration" envconfig:"RECIPIENT_USER_REGISTRATION"`
|
UserRegistration string `json:"UserRegistration" envconfig:"RECIPIENT_USER_REGISTRATION"`
|
||||||
|
AdminEmail string `json:"AdminEmail" envconfig:"ADMIN_MAIL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SecurityConfig struct {
|
type SecurityConfig struct {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type RelayContactRequestTest struct {
|
|||||||
Assert bool
|
Assert bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContactController(t *testing.T) {
|
func testContactController(t *testing.T) {
|
||||||
|
|
||||||
tests := getContactData()
|
tests := getContactData()
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -104,15 +104,15 @@ func TestSuite(t *testing.T) {
|
|||||||
// code := m.Run()
|
// code := m.Run()
|
||||||
|
|
||||||
t.Run("userController", func(t *testing.T) {
|
t.Run("userController", func(t *testing.T) {
|
||||||
TestUserController(t)
|
testUserController(t)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("contactController", func(t *testing.T) {
|
t.Run("contactController", func(t *testing.T) {
|
||||||
TestContactController(t)
|
testContactController(t)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("membershipController", func(t *testing.T) {
|
t.Run("membershipController", func(t *testing.T) {
|
||||||
TestMembershipController(t)
|
testMembershipController(t)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := utils.SMTPStop(); err != nil {
|
if err := utils.SMTPStop(); err != nil {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type RegisterSubscriptionTest struct {
|
|||||||
Assert bool
|
Assert bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMembershipController(t *testing.T) {
|
func testMembershipController(t *testing.T) {
|
||||||
|
|
||||||
tests := getSubscriptionData()
|
tests := getSubscriptionData()
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func (rt *RegisterUserTest) ValidateResult() error {
|
|||||||
return validateUser(rt.Assert, rt.WantDBData)
|
return validateUser(rt.Assert, rt.WantDBData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserController(t *testing.T) {
|
func testUserController(t *testing.T) {
|
||||||
|
|
||||||
tests := getTestUsers()
|
tests := getTestUsers()
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/internal/constants"
|
||||||
"GoMembership/internal/models"
|
"GoMembership/internal/models"
|
||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alexedwards/argon2id"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -29,6 +34,9 @@ func Open(dbPath string) error {
|
|||||||
DB = db
|
DB = db
|
||||||
|
|
||||||
logger.Info.Print("Opened DB")
|
logger.Info.Print("Opened DB")
|
||||||
|
if err := seedDatabase(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,3 +48,42 @@ func Close() error {
|
|||||||
}
|
}
|
||||||
return db.Close()
|
return db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func seedDatabase() error {
|
||||||
|
var count int64
|
||||||
|
DB.Model(&models.User{}).Count(&count)
|
||||||
|
if count == 0 {
|
||||||
|
bytes := make([]byte, 12)
|
||||||
|
_, err := rand.Read(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
password := hex.EncodeToString(bytes)
|
||||||
|
hash, err := argon2id.CreateHash(password, argon2id.DefaultParams)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
admin := models.User{
|
||||||
|
FirstName: "ad",
|
||||||
|
LastName: "min",
|
||||||
|
DateOfBirth: time.Now(),
|
||||||
|
Password: hash,
|
||||||
|
Address: "Downhill 4",
|
||||||
|
ZipCode: "9999",
|
||||||
|
City: "TechTown",
|
||||||
|
Status: constants.ActiveStatus,
|
||||||
|
RoleID: constants.Roles.Editor,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := DB.Create(&admin)
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
logger.Error.Print("==============================================================")
|
||||||
|
logger.Error.Printf("Admin Password: %v", password)
|
||||||
|
logger.Error.Print("==============================================================")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
CREATE TABLE users (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
created_at DATETIME NOT NULL,
|
|
||||||
updated_at DATETIME NOT NULL,
|
|
||||||
first_name VARCHAR(50) NOT NULL,
|
|
||||||
last_name VARCHAR(50) NOT NULL,
|
|
||||||
phone VARCHAR(15),
|
|
||||||
email VARCHAR(100) NOT NULL UNIQUE,
|
|
||||||
password VARCHAR(255) NOT NULL,
|
|
||||||
salt VARCHAR(255) NOT NULL,
|
|
||||||
drivers_id_checked BOOLEAN,
|
|
||||||
role_id INT,
|
|
||||||
payment_status VARCHAR(50),
|
|
||||||
date_of_birth DATE,
|
|
||||||
address VARCHAR(255),
|
|
||||||
profile_picture VARCHAR(255),
|
|
||||||
notes TEXT,
|
|
||||||
status VARCHAR(50),
|
|
||||||
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE SET NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE banking (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
user_id INT,
|
|
||||||
iban VARCHAR(34) NOT NULL,
|
|
||||||
bic VARCHAR(11) NOT NULL,
|
|
||||||
mandate_reference VARCHAR(50),
|
|
||||||
mandate_date_signed DATE,
|
|
||||||
bank_name VARCHAR(100),
|
|
||||||
account_holder_name VARCHAR(100),
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE memberships (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
user_id INT NOT NULL,
|
|
||||||
parent_id INT,
|
|
||||||
model_id INT,
|
|
||||||
start_date DATE,
|
|
||||||
end_date DATE,
|
|
||||||
status VARCHAR(50),
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE membership_plans (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
monthly_fee DECIMAL(10, 2),
|
|
||||||
hourly_rate DECIMAL(10, 2),
|
|
||||||
included_hours_per_year INT,
|
|
||||||
included_hours_per_month INT,
|
|
||||||
conditions TEXT,
|
|
||||||
details TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE rentals (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
car_id INT,
|
|
||||||
user_id INT,
|
|
||||||
start_datetime DATETIME NOT NULL,
|
|
||||||
end_datetime DATETIME NOT NULL,
|
|
||||||
booking_datetime DATETIME NOT NULL,
|
|
||||||
total_cost DECIMAL(10, 2),
|
|
||||||
payment_method VARCHAR(50),
|
|
||||||
status VARCHAR(50),
|
|
||||||
FOREIGN KEY (car_id) REFERENCES cars(id),
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE roles (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
role_name VARCHAR(50) NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE consents (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
user_id INT,
|
|
||||||
updated_at DATE,
|
|
||||||
created_at DATE,
|
|
||||||
first_name VARCHAR(255),
|
|
||||||
last_name VARCHAR(255),
|
|
||||||
email VARCHAR(255),
|
|
||||||
consent_type VARCHAR(255),
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE cars (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
licence_plate VARCHAR(15) NOT NULL UNIQUE,
|
|
||||||
insurance VARCHAR(255) NOT NULL,
|
|
||||||
acquired_date DATE NOT NULL,
|
|
||||||
monthly_expenses DECIMAL(10, 2) NOT NULL,
|
|
||||||
make VARCHAR(50),
|
|
||||||
model VARCHAR(50),
|
|
||||||
year INT,
|
|
||||||
mileage INT,
|
|
||||||
last_service_date DATE,
|
|
||||||
status VARCHAR(50),
|
|
||||||
vin VARCHAR(17) UNIQUE,
|
|
||||||
fuel_type VARCHAR(20),
|
|
||||||
gps BOOLEAN,
|
|
||||||
current_location VARCHAR(255),
|
|
||||||
service_history TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE email_verifications (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
user_id INT,
|
|
||||||
verification_token VARCHAR(255) NOT NULL,
|
|
||||||
created_at DATETIME NOT NULL,
|
|
||||||
verified_at DATETIME DEFAULT NULL,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/internal/config"
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -15,6 +20,26 @@ import (
|
|||||||
func TestAuthMiddleware(t *testing.T) {
|
func TestAuthMiddleware(t *testing.T) {
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
|
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to get current working directory: %v", err)
|
||||||
|
}
|
||||||
|
configFilePath := filepath.Join(cwd, "..", "..", "configs", "config.json")
|
||||||
|
templateHTMLPath := filepath.Join(cwd, "..", "..", "templates", "html")
|
||||||
|
templateMailPath := filepath.Join(cwd, "..", "..", "templates", "email")
|
||||||
|
|
||||||
|
if err := os.Setenv("TEMPLATE_MAIL_PATH", templateMailPath); err != nil {
|
||||||
|
log.Fatalf("Error setting environment variable: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.Setenv("TEMPLATE_HTML_PATH", templateHTMLPath); err != nil {
|
||||||
|
log.Fatalf("Error setting environment variable: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.Setenv("CONFIG_FILE_PATH", configFilePath); err != nil {
|
||||||
|
log.Fatalf("Error setting environment variable: %v", err)
|
||||||
|
}
|
||||||
|
config.LoadConfig()
|
||||||
|
logger.Info.Printf("Config: %#v", config.CFG)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
setupAuth func(r *http.Request)
|
setupAuth func(r *http.Request)
|
||||||
@@ -31,15 +56,15 @@ func TestAuthMiddleware(t *testing.T) {
|
|||||||
expectedUserID: 123,
|
expectedUserID: 123,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Missing Auth Header",
|
name: "Missing Cookie",
|
||||||
setupAuth: func(r *http.Request) {},
|
setupAuth: func(r *http.Request) {},
|
||||||
expectedStatus: http.StatusUnauthorized,
|
expectedStatus: http.StatusUnauthorized,
|
||||||
expectedUserID: 0,
|
expectedUserID: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid Token Format",
|
name: "Invalid Token",
|
||||||
setupAuth: func(r *http.Request) {
|
setupAuth: func(r *http.Request) {
|
||||||
r.Header.Set("Authorization", "InvalidFormat")
|
r.AddCookie(&http.Cookie{Name: "jwt", Value: "InvalidToken"})
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusUnauthorized,
|
expectedStatus: http.StatusUnauthorized,
|
||||||
expectedUserID: 0,
|
expectedUserID: 0,
|
||||||
@@ -48,7 +73,7 @@ func TestAuthMiddleware(t *testing.T) {
|
|||||||
name: "Expired Token",
|
name: "Expired Token",
|
||||||
setupAuth: func(r *http.Request) {
|
setupAuth: func(r *http.Request) {
|
||||||
token := jwt.NewWithClaims(jwtSigningMethod, jwt.MapClaims{
|
token := jwt.NewWithClaims(jwtSigningMethod, jwt.MapClaims{
|
||||||
"user_id": "user123",
|
"user_id": 123,
|
||||||
"exp": time.Now().Add(-time.Hour).Unix(), // Expired 1 hour ago
|
"exp": time.Now().Add(-time.Hour).Unix(), // Expired 1 hour ago
|
||||||
})
|
})
|
||||||
tokenString, _ := token.SignedString(jwtKey)
|
tokenString, _ := token.SignedString(jwtKey)
|
||||||
@@ -61,7 +86,7 @@ func TestAuthMiddleware(t *testing.T) {
|
|||||||
name: "Invalid Signature",
|
name: "Invalid Signature",
|
||||||
setupAuth: func(r *http.Request) {
|
setupAuth: func(r *http.Request) {
|
||||||
token := jwt.NewWithClaims(jwtSigningMethod, jwt.MapClaims{
|
token := jwt.NewWithClaims(jwtSigningMethod, jwt.MapClaims{
|
||||||
"user_id": "user123",
|
"user_id": 123,
|
||||||
"exp": time.Now().Add(time.Hour).Unix(),
|
"exp": time.Now().Add(time.Hour).Unix(),
|
||||||
})
|
})
|
||||||
tokenString, _ := token.SignedString([]byte("wrong_secret"))
|
tokenString, _ := token.SignedString([]byte("wrong_secret"))
|
||||||
@@ -70,6 +95,19 @@ func TestAuthMiddleware(t *testing.T) {
|
|||||||
expectedStatus: http.StatusUnauthorized,
|
expectedStatus: http.StatusUnauthorized,
|
||||||
expectedUserID: 0,
|
expectedUserID: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid Signing Method",
|
||||||
|
setupAuth: func(r *http.Request) {
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.MapClaims{
|
||||||
|
"user_id": 123,
|
||||||
|
"exp": time.Now().Add(time.Hour).Unix(),
|
||||||
|
})
|
||||||
|
tokenString, _ := token.SignedString([]byte(config.Auth.JWTSecret))
|
||||||
|
r.AddCookie(&http.Cookie{Name: "jwt", Value: tokenString})
|
||||||
|
},
|
||||||
|
expectedStatus: http.StatusUnauthorized,
|
||||||
|
expectedUserID: 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user