From a007fc4c6e9758d11eb8f49f4315b31bda56c091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=81scar=20M=2E=20Lage?= Date: Fri, 15 Sep 2023 18:21:04 +0200 Subject: [PATCH] Initial commit --- .air.toml | 17 ++ .env.sample | 5 + .gitignore | 10 ++ README.md | 3 + cmd/api/main.go | 38 +++++ docker/.env.sample | 6 + docker/Dockerfile | 17 ++ docker/Makefile | 318 +++++++++++++++++++++++++++++++++++ docker/docker-compose.yml | 36 ++++ docker/scripts/entrypoint.sh | 43 +++++ go.mod | 21 +++ go.sum | 45 +++++ internal/config/config.go | 32 ++++ internal/data/controller.go | 32 ++++ internal/data/model.go | 17 ++ internal/data/routes.go | 22 +++ internal/server/routes.go | 71 ++++++++ internal/server/server.go | 30 ++++ 18 files changed, 763 insertions(+) create mode 100644 .air.toml create mode 100644 .env.sample create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cmd/api/main.go create mode 100644 docker/.env.sample create mode 100644 docker/Dockerfile create mode 100644 docker/Makefile create mode 100644 docker/docker-compose.yml create mode 100755 docker/scripts/entrypoint.sh create mode 100644 go.mod create mode 100644 go.sum create mode 100755 internal/config/config.go create mode 100755 internal/data/controller.go create mode 100755 internal/data/model.go create mode 100755 internal/data/routes.go create mode 100755 internal/server/routes.go create mode 100755 internal/server/server.go diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..500aea8 --- /dev/null +++ b/.air.toml @@ -0,0 +1,17 @@ +# Config file for [Air](https://github.com/cosmtrek/air) in TOML format + +# Working directory +# . or absolute path, please note that the directories following must be under root. +root = "." +tmp_dir = "tmp" + +[build] +# Just plain old shell command. You could use `make` as well. +cmd = "go build -gcflags=all=\"-N -l\" -o ./tmp/main ./cmd/api/main.go" +# Binary file yields from `cmd`. +bin = "tmp/main" +# Customize binary. +full_bin = "dlv exec --accept-multiclient --log --log-output=rpc,debugger --headless --continue --listen='0.0.0.0:40000' --api-version=2 ./tmp/main" + +# Watch these filename extensions. +include_ext = ["go", "tpl", "tmpl", "html"] diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..f017117 --- /dev/null +++ b/.env.sample @@ -0,0 +1,5 @@ +# App config +APP_PORT=8080 + +# JWT +JWT_KEY=jwtkey diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a0e2026 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/tmp +/docker/_data/mysql +/docker/_data/certs +/docker/_data/logs +.env +.env.test +.devcontainer.json +.vscode +debug.test +.dlv.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..62eae9e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Onyx API + +[API Endpoints](ENDPOINTS.md) diff --git a/cmd/api/main.go b/cmd/api/main.go new file mode 100644 index 0000000..6e0f2ec --- /dev/null +++ b/cmd/api/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "log" + "strconv" + + "onyx-api/internal/config" + "onyx-api/internal/server" +) + +func main() { + + // Load config + log.Println("Loading Server Configurations...") + cfg, err := config.LoadConfig() + if err != nil { + log.Fatalf("Error loading config: %v", err) + } + + // New server with proper config + App := server.NewServer(cfg, db, mail) + + // Load Router + err = App.Routes() + if err != nil { + log.Fatalf("Error Loading routes: %v", err) + } else { + log.Printf("Routes loaded.") + } + + // Run the server + err = App.Run() + if err != nil { + log.Fatalf("Error running the app: %v", err) + } else { + log.Printf("App up and running.") + } +} diff --git a/docker/.env.sample b/docker/.env.sample new file mode 100644 index 0000000..b0c0dd8 --- /dev/null +++ b/docker/.env.sample @@ -0,0 +1,6 @@ +# Docker environment (local, staging, production) +DOCKER_ENV=local + +# Nginx virtualhost (.env) +VPORT=8080 +DEBUG_PORT=40000 diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..d5a5012 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,17 @@ +# syntax=docker/dockerfile:1 + +FROM golang:1.19-alpine + +WORKDIR /code + +RUN apk add bash gcc-go musl-dev tzdata && \ + echo "=> Configuring and installing timezone/locale" && \ + export TZ=Europe/Madrid && \ + cp /usr/share/zoneinfo/Europe/Madrid /etc/localtime + + +COPY ./scripts/entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] +CMD ["run-server"] + +VOLUME /code diff --git a/docker/Makefile b/docker/Makefile new file mode 100644 index 0000000..3ef1698 --- /dev/null +++ b/docker/Makefile @@ -0,0 +1,318 @@ +## +# Makefile to help manage docker-compose services +# +# Built on top of those resources: +# https://gist.github.com/iNamik/cafef08f9d931cbf7acb012075052912 +# https://github.com/krom/docker-compose-makefile/tree/master/samples +# + +# Include environment files +include ../.env +include .env +export + +THIS_FILE := Makefile +DOCKER := docker +DOCKER_COMPOSE := docker-compose +DOCKER_COMPOSE_FILES := -f docker-compose.yml +ifeq ($(DOCKER_ENV),staging) + DOCKER_COMPOSE_FILES := -f docker-compose.yml +endif +ifeq ($(DOCKER_ENV),production) + DOCKER_COMPOSE_FILES := -f docker-compose.yml +endif + +CERT_DOMAIN := api.onyx.local +IMAGE_DEFAULT := onyx-api +CONTAINER_DEFAULT := onyx-api-1 +SERVICES_DEFAULT := api + +SERVICE_DEFAULT := api + +NETWORK := app +NETWORK_PROXY := nginx-proxy + +BACKUP_SERVICE := backup +RESTORE_SERVICE := restore + +SHELL_CMD := /bin/bash + +container ?= $(CONTAINER_DEFAULT) +image ?= $(IMAGE_DEFAULT) +service ?= +services ?= $(SERVICES_DEFAULT) +test ?= A +package ?= chargers + +.DEFAULT_GOAL := help + + +## +# help +# +help: +ifeq ($(CONTAINER_DEFAULT),) + $(warning WARNING: CONTAINER_DEFAULT is not set. Please edit makefile) +endif + @echo + @echo "Make targets:" + @echo + @cat $(THIS_FILE) | \ + sed -n -E 's/^([^.][^: ]+)\s*:(([^=#]*##\s*(.*[^[:space:]])\s*)|[^=].*)$$/ \1 \4/p' | \ + sort -u | \ + expand -t15 + @echo + @echo + @echo "Target arguments:" + @echo + @echo " " "service" "\t" "Target service for docker-compose actions (default=all-services)" + @echo " " " " "\t" " - make start" + @echo " " " " "\t" " - make start services=app" + @echo " " "services" "\t" "Target services for docker-compose actions (default=all-services, space separated)" + @echo " " " " "\t" " - make stop services='app mysql'" + @echo " " "container""\t" "Target container for docker actions (default='$(CONTAINER_DEFAULT)')" + @echo " " " " "\t" " - make bash container=$(container)" + @echo " " "image" "\t" "Target image for interactive shell (default='$(IMAGE_DEFAULT)')" + @echo " " " " "\t" " - make it image=$(image)" + @echo " " "test" "\t" "Run custom test (default='$(test)')" + @echo " " " " "\t" " - make test test=$(test)" + @echo " " "testdlv" "\t" "Run a 'dlv test' with a custom package (default='$(package)')" + @echo " " " " "\t" " - make testdlv package=$(package)" + +## +# services +# +services: ## Lists services + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) ps --services + + +## +# start +# +all: dev ## See 'dev' +start: dev ## See 'dev' +dev: ## Start containers for development [service|services] + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) up -d $(services) + $(MAKE) logs + + +## +# stop +# +stop: ## Stop containers [service|services] + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) stop $(services) + + +## +# restart +# +restart: ## Restart containers [service|services] + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) restart $(services) + $(MAKE) logs + + +## +# down +# +down: ## Removes containers (preserves images and volumes) + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down + + +create-network: +ifeq ($(DOCKER_ENV),local) + @echo + @echo "Creating proper network ($(NETWORK)) for the project" + @$(DOCKER) network create $(NETWORK) 2> /dev/null || true + @echo "Creating proper network ($(NETWORK_PROXY)) for the nginx proxy" + @$(DOCKER) network create $(NETWORK_PROXY) 2> /dev/null || true +endif + +## +# build +# +build: create-network ## Builds service images [service|services] +ifeq ($(DOCKER_ENV),local) + if [ ! -d "_data/certs" ]; then mkdir -p "_data/certs"; fi + test -f _data/certs/$(CERT_DOMAIN).key && test -f _data/certs/$(CERT_DOMAIN).crt || mkcert -key-file _data/certs/$(CERT_DOMAIN).key -cert-file _data/certs/$(CERT_DOMAIN).crt $(CERT_DOMAIN) "*.$(CERT_DOMAIN)" +endif + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) build $(services) + + +## +# rebuild +# +rebuild: ## Build containers without cache [service|services] + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) build --no-cache $(services) + + +## +# ps +# +status: ps ## See 'ps' +ps: ## Show status of containers + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) ps + +## +# interact +# +interact: it ## See 'it' +it: ## Run a new container in interactive mode. Needs image name [image] +ifeq ($(image),) + $(error ERROR: 'image' is not set. Please provide 'image=' argument or edit makefile and set CONTAINER_DEFAULT) +endif + @echo + @echo "Starting interactive shell ($(SHELL_CMD)) in image container '$(image)'" + @$(DOCKER) run -it --entrypoint "$(SHELL_CMD)" $(image) + + +## +# bash +# +sh: bash ## See 'bash' +shell: bash ## See 'bash' +bash: ## Brings up a shell in default (or specified) container [container] +ifeq ($(container),) + $(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT) +endif + @echo + @echo "Starting shell ($(SHELL_CMD)) in container '$(container)'" + @$(DOCKER) exec -it "$(container)" "$(SHELL_CMD)" + + +## +# attach +# +at: attach ## See 'attach' +attach: ## Attach to a running container [container] +ifeq ($(container),) + $(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT) +endif + @echo + @echo "Attaching to '$(container)'" + @$(DOCKER) attach $(container) + + +## +# log +# +log: ## Shows log from a specific container (in 'follow' mode) [container] +ifeq ($(container),) + $(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT) +endif + @echo + @echo "Log in $(container)" + @$(DOCKER) logs -f $(container) + + +## +# logs +# +logs: ## Shows output of running containers (in 'follow' mode) [service|services] + @echo + @echo "Logs in $(services)" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) logs -f $(services) + + +## +# rmimages +# +rmimages: ## Remove images + @echo + @echo "Remove local images" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down --rmi local + + +## +# rmvols +# +rmvols: ## Remove volumes + @echo + @echo "Remove named volumes declared in the volumes section of the Compose file and anonymous volumes attached to containers" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down -v + + +## +# rm +# +rm: rmimages rmvols ## Remove volumes and images + +## +# clean +# +clean: ## Remove containers, images and volumes + @echo + @echo "Remove containers, images and volumes" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down --volumes --rmi all + + +## +# backup +# +backup: ## Run 'backup' service + @echo + @echo "Running '$(BACKUP_SERVICE)'" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) run $(BACKUP_SERVICE) + + +## +# restore +# +restore: ## Run 'restore' service + @echo + @echo "Running '$(BACKUP_SERVICE)'" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) run $(RESTORE_SERVICE) + +## +# tests +# +tests: ## Run all the battery tests + @echo + @echo "Running tests" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) run --rm tests + +## +# test +# +test: ## Run 'tests' service with a custom test [test=A] +ifneq ($(DOCKER_ENV),production) + @echo + @echo "Running test $(test)" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) run --rm tests gotest -v -run $(test) ./... +endif + + +## +# testdlv +# +testdlv: ## Run a 'dlv test' with a custom package for debug purposes [package=chargers] +ifneq ($(DOCKER_ENV),production) + @echo + @echo "Running test $(test)" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) run --rm tests dlv test /code/internal/$(package) +endif + + +## +# recreate_test_db +# +recreate_test_db: ## Recrete test db +ifneq ($(DOCKER_ENV),production) + @echo + @echo "Recreate test db from init sql schemas" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) stop $(MYSQL_TEST) + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) rm $(MYSQL_TEST) + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) up -d $(MYSQL_TEST) +endif + + +## +# dumplog +# +dumplog: ## Run 'dumplog' [service|services] + if [ ! -d "_data/logs" ]; then mkdir -p "_data/logs"; fi + @echo + @echo "Running 'dumplog'" + @$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) logs --no-color --since 24h --timestamps $(services) + + +.PHONY: help services all start dev stop restart down create-network build rebuild status ps interact it sh shell bash at attach log logs rm rmimages rmvols clean backup restore tests test testdlv recreate_test_db dumplog diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..c275c39 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.7" +name: "onyx" + +# Services +services: + + # App + api: + build: . + env_file: + - ./.env + - ../.env + restart: unless-stopped + command: ["run-server"] + stdin_open: true + tty: true + ports: + - ${VPORT}:${VPORT} + - ${DEBUG_PORT}:${DEBUG_PORT} + environment: + - VIRTUAL_HOST=${VHOST} + - VIRTUAL_PORT=${VPORT} + networks: + - app + - default + volumes: + - ../:/code/ + +# Docker Networks +networks: + default: + name: nginx-proxy + external: true + app: + driver: bridge + diff --git a/docker/scripts/entrypoint.sh b/docker/scripts/entrypoint.sh new file mode 100755 index 0000000..a23ece1 --- /dev/null +++ b/docker/scripts/entrypoint.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +function wait_service { + echo -e "\n-> Waiting for service $1, $2...\n" + while ! nc -z $1 $2; do + exec sleep 1 + done +} + +function install_general_dependencies { + echo -e "\n-> Installing general dependencies...\n" + go get -u github.com/cosmtrek/air + go install github.com/cosmtrek/air + go install github.com/go-delve/delve/cmd/dlv@latest + +} + +function install_app_dependencies { + echo -e "\n-> Installing app dependencies...\n" + cd /code + go mod tidy +} + +case $1 in + run-server) + wait_service $DATABASE_HOST $DATABASE_PORT + install_general_dependencies + install_app_dependencies + echo -e "\n-> Run server...\n" + exec air + ;; + run-tests) + install_app_dependencies + echo -e "\n-> Run tests...\n" + exec gotest -v ./... + ;; + *) + exec "$@" + ;; +esac + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8759cfd --- /dev/null +++ b/go.mod @@ -0,0 +1,21 @@ +module onyx-api + +go 1.19 + +require ( + github.com/joho/godotenv v1.5.1 + github.com/labstack/echo/v4 v4.11.1 + github.com/mitchellh/mapstructure v1.5.0 +) + +require ( + github.com/labstack/gommon v0.4.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5e6a25f --- /dev/null +++ b/go.sum @@ -0,0 +1,45 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= +github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +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/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100755 index 0000000..f93aeaa --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/joho/godotenv" + "github.com/mitchellh/mapstructure" +) + +type Config struct { + AppPortListen string `mapstructure:"APP_PORT"` + JwtKey []byte +} + +func LoadConfig(filename ...string) (*Config, error) { + var myenv map[string]string + var err error + var c Config + + if len(filename) == 0 { + myenv, err = godotenv.Read() + } else { + myenv, err = godotenv.Read(filename[0]) + } + + if err != nil { + return nil, err + } + + mapstructure.Decode(myenv, &c) + c.JwtKey = []byte(c.StringKey) + + return &c, nil +} diff --git a/internal/data/controller.go b/internal/data/controller.go new file mode 100755 index 0000000..71d3c9b --- /dev/null +++ b/internal/data/controller.go @@ -0,0 +1,32 @@ +package data + +import ( + "errors" + "net/http" + "onyx-api/internal/config" + + "github.com/labstack/echo/v4" +) + +type Controller struct { + cfg *config.Config + dataRepo dataRepo +} + +// New controller constructor +func NewController(cfg *config.Config) *Controller { + return &Controller{cfg: cfg} +} + +func (c *Controller) Ping() echo.HandlerFunc { + return func(e echo.Context) error { + return e.JSON(http.StatusOK, "pong") + } +} + +func (c *Controller) GetAllProjects() echo.HandlerFunc { + return func(e echo.Context) error { + projets := ["Uno", "Dos", Tres] + return e.JSON(http.StatusOK, chargers) + } +} \ No newline at end of file diff --git a/internal/data/model.go b/internal/data/model.go new file mode 100755 index 0000000..af84972 --- /dev/null +++ b/internal/data/model.go @@ -0,0 +1,17 @@ +package data + +type Project struct { + Name string `json:"name"` + Issues []Issues `json:"issues"` + Notes []Notes `json:"notes"` +} + +type Issues struct { + Description string `json:"description"` + Status string `json:"status"` +} + +type Notes struct { + Description string `json:"description"` + Status string `json:"status"` +} diff --git a/internal/data/routes.go b/internal/data/routes.go new file mode 100755 index 0000000..9294362 --- /dev/null +++ b/internal/data/routes.go @@ -0,0 +1,22 @@ +package chargers + +import ( + "onyx-api/internal/config" + + "github.com/labstack/echo/v4" +) + +type Routes struct { + cfg *config.Config + controller *Controller +} + +// New controller constructor +func NewRouter(cfg *config.Config, Controller *Controller) *Routes { + return &Routes{cfg: cfg, controller: Controller} +} + +func (r *Routes) MapRoutes(g *echo.Group) { + g.GET("/", r.controller.Ping()) + g.GET("/all", r.controller.GetAllProjects()) +} diff --git a/internal/server/routes.go b/internal/server/routes.go new file mode 100755 index 0000000..0fc9f9d --- /dev/null +++ b/internal/server/routes.go @@ -0,0 +1,71 @@ +package server + +import ( + // github.com/labstack/echo/v4" + //"github.com/golang-jwt/jwt/v4" + //echojwt "github.com/labstack/echo-jwt" + "api-users/internal/chargers" + "api-users/internal/users" + //"api-users/internal/auth" +) + +func (s *Server) Routes() error { + + // Init repositories + usersRepo := users.NewUsersRepository(s.db) + chargersRepo := chargers.NewChargersRepository(s.db) + + // Init controllers + usersController := users.NewUsersController(s.config, usersRepo, s.mailer) + chargersController := chargers.NewChargersController(s.config, chargersRepo) + + // Init custom routes + usersRoutes := users.NewUsersRouter(s.config, usersController) + chargersRoutes := chargers.NewChargersRouter(s.config, chargersController) + + //chargersHttp := chargers.NewChargersHttpHandlers + + // Set routes + e := s.router + v1 := e.Group("/api/v1") + + // Users routes + // usersGroup := v1.Group("/users") + usersRoutes.MapUsersRoutes(v1) + + // Chargers routes + chargersGroup := v1.Group("/chargers") + chargersRoutes.MapChargersRoutes(chargersGroup) + + return nil + /*log.Println("Loading routes...") + s.Router = echo.New() + //router_config := echojwt.Config{ + // SigningKey: s.Config.JwtKey, + // NewClaimsFunc: func(c echo.Context) jwt.Claims { + // return new(auth.JWTClaim) + // }, + //} + + // Init repositories + // userRepo := usersRepository.NewUsersRepository(s.DB) + chargerRepo := chargersRepo.NewChargersRepo(s.DB) + + api := s.Router.Group("/api") + { + // Users + // api.POST("/auth", controllers.GenerateToken) + // secured := api.Group("/user") + // { + // secured.Use(echojwt.WithConfig(router_config)) + // secured.GET("", controllers.GetUser) + // } + + // Chargers + // api.GET("/chargers", controllers.GetChargers) + api.GET("/chargers/all", chargerRepo.GetAllChargers) + // api.GET("/chargers/:id", controllers.GetChargerByID) + // api.GET("/chargers/search/:q", controllers.SearchChargers) + } + return nil*/ +} diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100755 index 0000000..f3aef14 --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,30 @@ +package server + +import ( + "log" + + "onyx-api/internal/config" + + "github.com/labstack/echo/v4" +) + +var err error + +type Server struct { + router *echo.Echo + config *config.Config +} + +func NewServer(cfg *config.Config) *Server { + return &Server{config: cfg, router: echo.New()} +} + +func (s *Server) Run() error { + err = s.router.Start(":" + s.config.AppPortListen) + if err != nil { + log.Printf("Error starting Server") + return err + } + + return nil +}