diff --git a/.gitignore b/.gitignore index b0d4aea..fcacf7e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules build dist taskfile.yml +*.db \ No newline at end of file diff --git a/.sample.env b/.sample.env index 7f594e5..5e25db6 100644 --- a/.sample.env +++ b/.sample.env @@ -1,2 +1,3 @@ +DB_TYPE=postgres # sqlite | postgres POSTGRES_DSN=postgres://postgres:postgres@localhost:5432/upstat?sslmode=disable JWT_SECRET_KEY=abcd diff --git a/Dockerfile b/Dockerfile index a4c575a..5c42607 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,7 @@ FROM golang:1.21.3 AS build WORKDIR /app COPY . . RUN go mod download \ - && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . \ - && chmod +x ./startup.sh + && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . # Release Stage FROM alpine:3.18 AS release diff --git a/Dockerfile_sqlite b/Dockerfile_sqlite new file mode 100644 index 0000000..226deac --- /dev/null +++ b/Dockerfile_sqlite @@ -0,0 +1,16 @@ +# Build stage +FROM golang:1.21.3-alpine AS build +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN apk --no-cache add build-base sqlite-dev \ + && CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o main . + +# Release stage +FROM alpine:latest AS release +WORKDIR /app +COPY --from=build /app/main . +RUN apk --no-cache add dumb-init ca-certificates sqlite +EXPOSE 8000 +CMD ["dumb-init", "./main"] diff --git a/Makefile b/Makefile index 6669018..dd0ab5c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,13 @@ include .env APP_NAME = upstat -MIGRATIONS_DIR = $(PWD)/database/migrations +MIGRATIONS_DIR ?= $(PWD)/database/migrations/sqlite +ifeq ($(DB_type), postgres) + MIGRATIONS_DIR = $(PWD)/database/migrations/postgres +else ifeq ($(DB_type), sqlite) + MIGRATIONS_DIR = $(PWD)/database/migrations/sqlite +endif + export POSTGRES_DSN dev: @@ -36,4 +42,4 @@ migrate.down: goose -dir $(MIGRATIONS_DIR) postgres $(POSTGRES_DSN) down migrate.reset: - goose -dir $(MIGRATIONS_DIR) postgres $(POSTGRES_DSN) reset \ No newline at end of file + goose -dir $(MIGRATIONS_DIR) postgres $(POSTGRES_DSN) reset diff --git a/README.md b/README.md index a9497ff..a5b0f23 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ It needs more features but for now... - Ping chart - Certificate info - PWA +- Sqlite & Postgres database support And dozens of smaller features to be added. @@ -38,14 +39,20 @@ And dozens of smaller features to be added. ### 🐳 Docker +For Sqlite + ```bash -curl -O https://raw.githubusercontent.com/chamanbravo/upstat/main/docker-compose.yml +curl -O https://raw.githubusercontent.com/chamanbravo/upstat/main/docker-compose-sqlite.yml docker compose up ``` -Upstat is now running on http://localhost:3000 +For Postgres +```bash +curl -O https://raw.githubusercontent.com/chamanbravo/upstat/main/docker-compose.yml +docker compose up +``` -> 📝 While deploying make sure to edit the environments in docker-compose file +Upstat is now running on http://localhost ### 💪🏻 Non-Docker diff --git a/controllers/auth_controller.go b/controllers/auth_controller.go index 4db1a54..6ccbbd5 100644 --- a/controllers/auth_controller.go +++ b/controllers/auth_controller.go @@ -42,6 +42,14 @@ func SignUp(c *fiber.Ctx) error { }) } + hashedPassword, err := utils.HashAndSalt(user.Password) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "message": err.Error(), + }) + } + + user.Password = hashedPassword if err := queries.SaveUser(user); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "message": err.Error(), @@ -100,7 +108,7 @@ func SignIn(c *fiber.Ctx) error { return c.Status(400).JSON(errors) } - existingUser, err := queries.FindUserByUsernameAndPassword(user.Username, user.Password) + existingUser, err := queries.FindUserByUsername(user.Username) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "message": err.Error(), @@ -112,6 +120,12 @@ func SignIn(c *fiber.Ctx) error { }) } + if err = utils.CheckHash(existingUser.Password, user.Password); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "message": "Invalid username or password", + }) + } + tokens, err := utils.GenerateJWT(existingUser.Username, existingUser.Firstname, existingUser.Lastname) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ diff --git a/controllers/user_controller.go b/controllers/user_controller.go index 2086fa8..c5090f4 100644 --- a/controllers/user_controller.go +++ b/controllers/user_controller.go @@ -46,7 +46,7 @@ func UpdatePassword(c *fiber.Ctx) error { username := c.Locals("username").(string) - user, err := queries.FindUserByUsernameAndPassword(username, updatePasswordBody.CurrentPassword) + user, err := queries.FindUserByUsername(username) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", @@ -56,11 +56,24 @@ func UpdatePassword(c *fiber.Ctx) error { if user == nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Not found", + "message": "User does not exist", + }) + } + + if err = utils.CheckHash(user.Password, updatePasswordBody.CurrentPassword); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "message": "Invalid current password", }) } - err = queries.UpdatePassword(username, updatePasswordBody) + hashedNewPassword, err := utils.HashAndSalt(updatePasswordBody.NewPassword) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "message": err.Error(), + }) + } + + err = queries.UpdatePassword(username, hashedNewPassword) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", diff --git a/database/db.go b/database/db.go index 282e297..65623ad 100644 --- a/database/db.go +++ b/database/db.go @@ -12,13 +12,27 @@ import ( var DB *sql.DB -//go:embed migrations/*.sql -var embedMigrations embed.FS +//go:embed migrations/sqlite/*.sql +var embedMigrationsSqlite embed.FS + +//go:embed migrations/postgres/*.sql +var embedMigrationsPostgres embed.FS func DBConnect() error { - psqlInfo := os.Getenv("POSTGRES_DSN") + dbType := os.Getenv("DB_TYPE") + if dbType == "" { + dbType = "sqlite" + } var err error - DB, err = sql.Open("postgres", psqlInfo) + + switch dbType { + case "postgres": + DB, err = PostgresConnection() + case "sqlite": + DB, err = SqliteConnection() + default: + DB, err = SqliteConnection() + } if err != nil { return fmt.Errorf("could not connect to database: %v", err) @@ -28,13 +42,21 @@ func DBConnect() error { panic(err) } - goose.SetBaseFS(embedMigrations) + switch dbType { + case "postgres": + goose.SetBaseFS(embedMigrationsPostgres) + case "sqlite": + goose.SetBaseFS(embedMigrationsSqlite) + default: + goose.SetBaseFS(embedMigrationsSqlite) + } - if err := goose.SetDialect("postgres"); err != nil { + if err := goose.SetDialect(dbType); err != nil { panic(err) } - if err := goose.Up(DB, "migrations"); err != nil { + dbMigrationDir := fmt.Sprintf("migrations/%s", dbType) + if err := goose.Up(DB, dbMigrationDir); err != nil { panic(err) } diff --git a/database/migrations/20231229140812_init.sql b/database/migrations/postgres/20231229140812_init.sql similarity index 98% rename from database/migrations/20231229140812_init.sql rename to database/migrations/postgres/20231229140812_init.sql index 00d1b7a..030ae65 100644 --- a/database/migrations/20231229140812_init.sql +++ b/database/migrations/postgres/20231229140812_init.sql @@ -1,7 +1,5 @@ -- +goose Up -- +goose StatementBegin -CREATE EXTENSION pgcrypto; - CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(32) UNIQUE NOT NULL, diff --git a/database/migrations/20240803043203_incidents.sql b/database/migrations/postgres/20240803043203_incidents.sql similarity index 100% rename from database/migrations/20240803043203_incidents.sql rename to database/migrations/postgres/20240803043203_incidents.sql diff --git a/database/migrations/sqlite/20231229140812_init.sql b/database/migrations/sqlite/20231229140812_init.sql new file mode 100644 index 0000000..d8ff64e --- /dev/null +++ b/database/migrations/sqlite/20231229140812_init.sql @@ -0,0 +1,67 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username VARCHAR(32) UNIQUE NOT NULL, + email VARCHAR(50) UNIQUE NOT NULL, + firstname VARCHAR(32) DEFAULT '', + lastname VARCHAR(32) DEFAULT '', + password text NOT NULL +); + +CREATE TABLE monitors ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(32) NOT NULL, + url VARCHAR(50) NOT NULL, + type VARCHAR(50) NOT NULL, + method VARCHAR(50) NOT NULL, + frequency INTEGER NOT NULL, + status VARCHAR(50) NOT NULL +); + +CREATE TABLE heartbeats ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + monitor_id INTEGER REFERENCES monitors(id) ON DELETE CASCADE NOT NULL, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + status_code VARCHAR(50) NOT NULL, + status VARCHAR(50) NOT NULL, + latency INTEGER NOT NULL, + message TEXT NOT NULL +); + +CREATE TABLE notifications ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(32) NOT NULL, + provider VARCHAR(50) NOT NULL, + data json NOT NULL +); + +CREATE TABLE notifications_monitors ( + monitor_id INTEGER REFERENCES monitors(id) ON DELETE CASCADE NOT NULL, + notification_id INTEGER REFERENCES notifications(id) ON DELETE CASCADE NOT NULL, + PRIMARY KEY (monitor_id, notification_id) +); + +CREATE TABLE status_pages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(32) NOT NULL, + slug VARCHAR(32) NOT NULL +); + +CREATE TABLE status_pages_monitors ( + monitor_id INTEGER REFERENCES monitors(id) ON DELETE CASCADE NOT NULL, + status_pages_id INTEGER REFERENCES status_pages(id) ON DELETE CASCADE NOT NULL, + PRIMARY KEY (monitor_id, status_pages_id) +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE users; +DROP TABLE monitors; +DROP TABLE heartbeats; +DROP TABLE notifications; +DROP TABLE notifications_monitors; +DROP TABLE status_pages; +DROP TABLE status_pages_monitors; +-- +goose StatementEnd diff --git a/database/migrations/sqlite/20240819135056_incidents.sql b/database/migrations/sqlite/20240819135056_incidents.sql new file mode 100644 index 0000000..77d8a5f --- /dev/null +++ b/database/migrations/sqlite/20240819135056_incidents.sql @@ -0,0 +1,15 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE incidents ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + type VARCHAR(50) NOT NULL, + description TEXT NOT NULL, + is_positive BOOLEAN DEFAULT true, + monitor_id INTEGER REFERENCES monitors(id) ON DELETE CASCADE NOT NULL +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE incidents; +-- +goose StatementEnd diff --git a/database/postgres.go b/database/postgres.go new file mode 100644 index 0000000..65a7488 --- /dev/null +++ b/database/postgres.go @@ -0,0 +1,14 @@ +package database + +import ( + "database/sql" + "os" + + _ "github.com/lib/pq" +) + +func PostgresConnection() (*sql.DB, error) { + psqlInfo := os.Getenv("POSTGRES_DSN") + db, err := sql.Open("postgres", psqlInfo) + return db, err +} diff --git a/database/sqlite.go b/database/sqlite.go new file mode 100644 index 0000000..b17b9e6 --- /dev/null +++ b/database/sqlite.go @@ -0,0 +1,13 @@ +package database + +import ( + "database/sql" + + _ "github.com/mattn/go-sqlite3" +) + +func SqliteConnection() (*sql.DB, error) { + sqliteDSN := "upstat.db" + db, err := sql.Open("sqlite3", sqliteDSN) + return db, err +} diff --git a/docker-compose-sqlite.yml b/docker-compose-sqlite.yml new file mode 100644 index 0000000..5055ba4 --- /dev/null +++ b/docker-compose-sqlite.yml @@ -0,0 +1,20 @@ +version: "3.4" +services: + api: + restart: unless-stopped + image: chamanbravo/upstat-api-sqlite:latest + environment: + - JWT_SECRET_KEY=asdfjaskljdaq123#!@810248)_+12 + volumes: + - sqlite_data:/app + + web: + restart: unless-stopped + image: chamanbravo/upstat-web:latest + ports: + - "3000:3000" + depends_on: + - api + +volumes: + sqlite_data: diff --git a/docker-compose.yml b/docker-compose.yml index edf0361..bb4b381 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' +version: "3.4" services: db: restart: unless-stopped @@ -9,7 +9,7 @@ services: volumes: - postgres_data:/var/lib/postgresql/data healthcheck: - test: [ "CMD-SHELL", "pg_isready -U postgres" ] + test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 @@ -18,8 +18,9 @@ services: restart: unless-stopped image: chamanbravo/upstat-api:latest environment: + - DB_TYPE=postgres - POSTGRES_DSN=postgres://postgres:postgres@db:5432/upstat?sslmode=disable - - JWT_SECRET_KEY=asdfjaskljd + - JWT_SECRET_KEY=asdfjaskljdaq123#!@810248)_+12 depends_on: db: condition: service_healthy diff --git a/go.mod b/go.mod index e3d36a9..c9b48f9 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,9 @@ require ( github.com/gofiber/fiber/v2 v2.50.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/joho/godotenv v1.5.1 + github.com/mattn/go-sqlite3 v1.14.22 + github.com/swaggo/swag v1.16.2 + golang.org/x/crypto v0.21.0 ) require ( @@ -24,9 +27,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/swaggo/swag v1.16.2 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.17.0 // indirect golang.org/x/tools v0.16.1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -50,8 +51,8 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.50.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 5147d21..93ddb89 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,6 @@ github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7N github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/gofiber/fiber/v2 v2.49.2 h1:ONEN3/Vc+dUCxxDgZZwpqvhISgHqb+bu+isBiEyKEQs= -github.com/gofiber/fiber/v2 v2.49.2/go.mod h1:gNsKnyrmfEWFpJxQAV0qvW6l70K1dZGno12oLtukcts= github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw= github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw= github.com/gofiber/swagger v0.1.14 h1:o524wh4QaS4eKhUCpj7M0Qhn8hvtzcyxDsfZLXuQcRI= @@ -112,6 +110,7 @@ github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= @@ -129,10 +128,13 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -189,8 +191,6 @@ github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkC github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.49.0 h1:9FdvCpmxB74LH4dPb7IJ1cOSsluR07XG3I1txXWwJpE= -github.com/valyala/fasthttp v1.49.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M= github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= @@ -217,8 +217,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -232,8 +232,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -250,8 +250,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= @@ -283,6 +283,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/queries/user.go b/queries/user.go index a665f1e..c13dbe7 100644 --- a/queries/user.go +++ b/queries/user.go @@ -10,7 +10,7 @@ import ( ) func SaveUser(u *dto.UserSignUp) error { - stmt, err := database.DB.Prepare("INSERT INTO users(username, email, password) VALUES($1, $2, crypt($3, gen_salt('bf')))") + stmt, err := database.DB.Prepare("INSERT INTO users(username, email, password) VALUES($1, $2, $3)") if err != nil { log.Println("Error when trying to prepare statement") log.Println(err) @@ -51,7 +51,7 @@ func FindUserByUsernameAndEmail(u *dto.UserSignUp) (*models.User, error) { } func FindUserByUsernameAndPassword(username, password string) (*models.User, error) { - stmt, err := database.DB.Prepare("SELECT id, username, email, firstname, lastname FROM users WHERE username = $1 AND password = crypt($2, password)") + stmt, err := database.DB.Prepare("SELECT id, username, email, firstname, lastname FROM users WHERE username = $1 AND password = $2") if err != nil { log.Println("Error when trying to prepare statement") log.Println(err) @@ -73,7 +73,7 @@ func FindUserByUsernameAndPassword(username, password string) (*models.User, err } func FindUserByUsername(username string) (*models.User, error) { - stmt, err := database.DB.Prepare("SELECT id, username, email, firstname, lastname FROM users WHERE username = $1") + stmt, err := database.DB.Prepare("SELECT id, username, email, firstname, lastname, password FROM users WHERE username = $1") if err != nil { log.Println("Error when trying to prepare statement") log.Println(err) @@ -82,7 +82,7 @@ func FindUserByUsername(username string) (*models.User, error) { defer stmt.Close() user := new(models.User) - result := stmt.QueryRow(username).Scan(&user.ID, &user.Username, &user.Email, &user.Firstname, &user.Lastname) + result := stmt.QueryRow(username).Scan(&user.ID, &user.Username, &user.Email, &user.Firstname, &user.Lastname, &user.Password) if result != nil { if result == sql.ErrNoRows { return nil, nil @@ -114,8 +114,8 @@ func UsersCount() (int, error) { return count, nil } -func UpdatePassword(username string, u *dto.UpdatePasswordIn) error { - stmt, err := database.DB.Prepare("UPDATE users SET password = crypt($2, gen_salt('bf')) WHERE username = $1 AND password = crypt($3, password)") +func UpdatePassword(username string, newPassword string) error { + stmt, err := database.DB.Prepare("UPDATE users SET password = $1 WHERE username = $2") if err != nil { log.Println("Error when trying to prepare statement") log.Println(err) @@ -123,7 +123,7 @@ func UpdatePassword(username string, u *dto.UpdatePasswordIn) error { } defer stmt.Close() - _, err = stmt.Exec(username, u.NewPassword, u.CurrentPassword) + _, err = stmt.Exec(newPassword, username) if err != nil { log.Println("Error when trying to update password") log.Println(err) diff --git a/startup.sh b/startup.sh deleted file mode 100644 index ec6082c..0000000 --- a/startup.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -# Create the database -PGPASSWORD=$PASSWORD psql -h $POSTGRES_HOST -p $POSTGRES_PORT -U $POSTGRES_USER -c "CREATE DATABASE $DB_NAME;" - -echo "Database '$DB_NAME' created successfully." diff --git a/utils/bcrypt_hash.go b/utils/bcrypt_hash.go new file mode 100644 index 0000000..73484de --- /dev/null +++ b/utils/bcrypt_hash.go @@ -0,0 +1,15 @@ +package utils + +import ( + "golang.org/x/crypto/bcrypt" +) + +func HashAndSalt(text string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(text), bcrypt.DefaultCost) + return string(hash), err +} + +func CheckHash(hash string, input string) error { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(input)) + return err +} diff --git a/web/components/register-form.tsx b/web/components/register-form.tsx index 1634e9c..a7393fd 100644 --- a/web/components/register-form.tsx +++ b/web/components/register-form.tsx @@ -51,7 +51,7 @@ export default function RegisterForm() { async function onSubmit(formData: RegisterFormValues) { try { setLoading(true); - const response = await fetch("/api/auth/signup/", { + const response = await fetch("/api/auth/signup", { method: "POST", headers: { "Content-Type": "application/json", diff --git a/web/components/status-pages/recent-ping-chart.tsx b/web/components/status-pages/recent-ping-chart.tsx index c933b31..624a971 100644 --- a/web/components/status-pages/recent-ping-chart.tsx +++ b/web/components/status-pages/recent-ping-chart.tsx @@ -24,7 +24,7 @@ const CustomTooltip = ({ }: TooltipProps) => { if (active && payload && payload.length) { return ( -
+

{labelFormatter ? labelFormatter(label, payload) : label}

@@ -52,7 +52,7 @@ interface Props { export default function RecentPingChart({ heartbeat }: Props) { return ( -
+