Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/sqlite support #43

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .sample.env
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
DB_TYPE="sqlite"
POSTGRES_USER="postgres"
POSTGRES_PASSWORD="postgres"
POSTGRES_DB="upstat"
POSTGRES_HOST="localhost" #if running in docker replace localhost with db
POSTGRES_PORT="5432"
POSTGRES_DSN="postgres://postgres:postgres@localhost:5432/upstat?sslmode=disable" #if running in docker replace localhost with db
SQLITE_DSN="upstat.db" # if running in docker replace upstat.db with /var/lib/upstat.db
JWT_SECRET_KEY="abcd"
IPADDR="0.0.0.0"
PORT="80"
22 changes: 18 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
FROM golang:1.21.3 AS build
FROM golang:1.21.3-alpine AS build
WORKDIR /app
COPY . .
COPY go.mod go.sum ./
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
RUN chmod +x ./startup.sh
COPY . .
ARG DB_TYPE
ARG CGO_ENABLED
RUN if [ "$DB_TYPE" = "sqlite" ]; then \
apk -U upgrade \
&& apk add --no-cache build-base; \
fi
RUN CGO_ENABLED=$CGO_ENABLED GOOS=linux go build -a -installsuffix cgo -o main .
RUN if [ "$DB_TYPE" = "postgres" ]; then \
chmod +x ./startup.sh; \
fi

FROM alpine:latest as release
WORKDIR /app
ARG DB_TYPE
COPY --from=build /app/main .
RUN apk -U upgrade \
&& apk add --no-cache dumb-init ca-certificates \
&& chmod +x /app/main
RUN if [ "$DB_TYPE" = "sqlite" ]; then \
apk add --no-cache sqlite \
&& sqlite3 /var/lib/sqlite_data/upstat.db; \
fi
EXPOSE 8000
CMD ["./main"]
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@ And dozens of smaller features to be added.

### 🐳 Docker

For default Sqlite users

```bash
docker compose up
```

For Postgres users
```bash
docker compose -f docker-compose.postgres.yml up
```

Upstat is now running on http://localhost

### 💪🏻 Non-Docker
Expand Down
16 changes: 15 additions & 1 deletion controllers/auth_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,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(),
Expand Down Expand Up @@ -101,7 +109,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(),
Expand All @@ -113,6 +121,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{
Expand Down
17 changes: 15 additions & 2 deletions controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func UpdatePassword(c *fiber.Ctx) error {

username := payload.Username

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",
Expand All @@ -71,11 +71,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",
Expand Down
33 changes: 26 additions & 7 deletions database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@ 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")
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)
Expand All @@ -28,13 +39,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)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
-- +goose Up
-- +goose StatementBegin
CREATE EXTENSION pgcrypto;

CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(32) UNIQUE NOT NULL,
Expand Down
67 changes: 67 additions & 0 deletions database/migrations/sqlite/20231229140812_init.sql
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions database/postgres.go
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 14 additions & 0 deletions database/sqlite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package database

import (
"database/sql"
"os"

_ "github.com/mattn/go-sqlite3"
)

func SqliteConnection() (*sql.DB, error) {
sqliteInfo := os.Getenv("SQLITE_DSN")
db, err := sql.Open("sqlite3", sqliteInfo)
return db, err
}
49 changes: 49 additions & 0 deletions docker-compose.postgres.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: '3.4'
services:
db:
restart: unless-stopped
image: postgres:13-alpine
env_file:
- .env
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
timeout: 5s
retries: 5

api:
restart: unless-stopped
build:
context: ./
args:
DB_TYPE: "postgres"
CGO_ENABLED: 0
env_file:
- .env
depends_on:
db:
condition: service_healthy

web:
restart: unless-stopped
build:
context: web
depends_on:
db:
condition: service_healthy

nginx:
restart: unless-stopped
image: nginx:1.21.1-alpine
ports:
- "$IPADDR:$PORT:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- api
- web

volumes:
postgres_data:
29 changes: 6 additions & 23 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
version: '3.4'
services:
db:
restart: unless-stopped
image: postgres:13-alpine
env_file:
- .env
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
timeout: 5s
retries: 5

api:
restart: unless-stopped
build:
context: ./
args:
DB_TYPE: "sqlite"
CGO_ENABLED: 1
env_file:
- .env
depends_on:
db:
condition: service_healthy
volumes:
- sqlite_data:/var/lib/sqlite_data

web:
restart: unless-stopped
build:
context: web
depends_on:
db:
condition: service_healthy

nginx:
restart: unless-stopped
Expand All @@ -38,9 +24,6 @@ services:
- "$IPADDR:$PORT:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- api
- web

volumes:
postgres_data:
sqlite_data:
Loading