Skip to content

Commit

Permalink
Merge pull request #141 from Tibz-Dankan/refactor/dir-structure
Browse files Browse the repository at this point in the history
Refactor/dir structure
  • Loading branch information
Tibz-Dankan authored Aug 26, 2024
2 parents a39215a + 1e58b20 commit a1c1581
Show file tree
Hide file tree
Showing 23 changed files with 924 additions and 78 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/deploy-to-render.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: Deploy To Render

on:
push:
branches:
- main
workflow_dispatch:
workflow_run:
workflows: ["Tests"]
types:
- completed

jobs:
deploy:
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Tests

on:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

env:
APPCRONS_STAG_DSN: ${{ secrets.APPCRONS_STAG_DSN }}

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.23"

- name: Install dependencies
run: make install

- name: Run tests
run: make stage # Runs tests in the staging environment

- name: Trigger deployment
if: success()
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/actions/workflows/deploy-to-render.com.yml/dispatches \
-d '{"ref": "${{ github.ref_name }}"}'
61 changes: 13 additions & 48 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,63 +1,28 @@
# Variables
APP_NAME := Appcrons
CMD_DIR := ./cmd
BIN_DIR := ./bin
TEST_DIR := ./test
TEST_DIR := ./tests

# Ensure bin directory exists
$(BIN_DIR):
@mkdir -p $(BIN_DIR)

# Default target
.PHONY: all
all: install run

# Run the development server
# Runs the development server
.PHONY: run
run:
@echo "Starting development server..."
@go run $(CMD_DIR)
@GO_ENV=development go run $(CMD_DIR)

# Run tests
# Runs tests in the development environment
.PHONY: test
test:
@echo "Running tests..."
@go test $(TEST_DIR) -v
@echo "Running tests with GO_ENV=testing..."
@GO_ENV=testing go test -v $(TEST_DIR)/...

# Install dependencies
# Runs tests in the staging environment
.PHONY: stage
stage:
@echo "Running tests with GO_ENV=staging..."
@GO_ENV=staging go test -v $(TEST_DIR)/...

# Installs the packages
.PHONY: install
install:
@echo "Installing dependencies..."
@go mod tidy
@go mod download

# Clean up
.PHONY: clean
clean:
@echo "Cleaning up..."
@go clean
@rm -rf $(BIN_DIR)

# Format code
.PHONY: fmt
fmt:
@echo "Formatting code..."
@go fmt $(CMD_DIR) $(TEST_DIR)

# Build the application
.PHONY: build
build: $(BIN_DIR)
@echo "Building application..."
@go build -o $(BIN_DIR)/$(APP_NAME) $(CMD_DIR)

# Run application in the background
.PHONY: start
start: $(BIN_DIR)
@echo "Starting application in the background..."
@nohup $(BIN_DIR)/$(APP_NAME) &

# Stop the application
.PHONY: stop
stop:
@echo "Stopping application..."
@pkill -f "$(BIN_DIR)/$(APP_NAME)"
6 changes: 6 additions & 0 deletions internal/middlewares/rateLimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package middlewares
import (
"log"
"net/http"
"os"
"sync"
"time"

Expand Down Expand Up @@ -50,6 +51,11 @@ func (rl *RateLimiter) AllowRequest(clientIp string) bool {

func RateLimit(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

if os.Getenv("GO_ENV") == "testing" || os.Getenv("GO_ENV") == "staging" {
next.ServeHTTP(w, r)
return
}
clientIP := r.Header.Get("X-Forwarded-For")
if clientIP == "" {
clientIP = r.Header.Get("X-Real-IP")
Expand Down
10 changes: 7 additions & 3 deletions internal/models/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models

import (
"encoding/json"
"errors"
"log"
"time"
)
Expand Down Expand Up @@ -45,17 +46,20 @@ func (p *Permissions) Set(userId string) error {
}

if savedUser.ID == "" {
log.Println("User does not exist!")
return nil //TODO: To return custom error message
return errors.New("User does not exist")
}

userPermissions.Role = savedUser.Role

if userPermissions.Role == "user" {
userPermissions.Permissions = []string{"READ", "WRITE", "EDIT", "DELETE"}
}

if userPermissions.Role == "client" {
userPermissions.Permissions = []string{"READ", "WRITE", "EDIT", "DELETE"}
}

if userPermissions.Role == "admin" {
if userPermissions.Role == "sys_admin" {
userPermissions.Permissions = []string{"READ"}
}

Expand Down
11 changes: 10 additions & 1 deletion internal/models/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
)

var db = config.Db()
var DB = db
var redisClient = config.RedisClient()
var ctx = context.Background()

Expand All @@ -21,14 +22,22 @@ func DBAutoMigrate() {
log.Println("Auto Migration successful")
}

func DBDropTables() {
err := db.Migrator().DropTable(&User{}, &App{}, &Request{}, &RequestTime{}, &Feedback{})
if err != nil {
log.Fatal("Failed to drop tables", err)
}
log.Println("Dropped all tables")
}

type User struct {
ID string `gorm:"column:id;type:uuid;primaryKey" json:"id"`
Name string `gorm:"column:name;not null;index" json:"name"`
Email string `gorm:"column:email;unique;not null;index" json:"email"`
Password string `gorm:"column:password;not null" json:"password"`
PasswordResetToken string `gorm:"column:passwordResetToken;index" json:"passwordResetToken"`
PasswordResetExpiresAt time.Time `gorm:"column:passwordResetExpiresAt;index" json:"passwordResetExpiresAt"`
Role string `gorm:"column:role;default:'admin';not null" json:"role"`
Role string `gorm:"column:role;default:'user';not null" json:"role"`
App []App `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"apps"`
Feedback []Feedback `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"feedbacks"`
CreatedAt time.Time `gorm:"column:createdAt" json:"createdAt"`
Expand Down
3 changes: 1 addition & 2 deletions internal/models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ func (u *User) HashPassword(plainTextPassword string) (string, error) {
}

func (u *User) ValidRole(role string) bool {
roles := []string{"admin", "client", "staff"}
// TODO: TO change roles to "user and sys_admin"
roles := []string{"user", "sys_admin"}

for _, r := range roles {
if r == role {
Expand Down
2 changes: 1 addition & 1 deletion internal/routes/auth/forgotPassword.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func forgotPassword(w http.ResponseWriter, r *http.Request) {

err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
services.AppError(err.Error(), 400, w)
services.AppError(err.Error(), 500, w)
return
}

Expand Down
15 changes: 12 additions & 3 deletions internal/routes/auth/resetPassword.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package auth

import (
"encoding/json"
"log"
"net/http"
"os"

"github.com/Tibz-Dankan/keep-active/internal/events"
"github.com/Tibz-Dankan/keep-active/internal/models"
Expand All @@ -16,7 +18,7 @@ func resetPassword(w http.ResponseWriter, r *http.Request) {

err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
services.AppError(err.Error(), 400, w)
services.AppError(err.Error(), 500, w)
return
}

Expand Down Expand Up @@ -51,6 +53,15 @@ func resetPassword(w http.ResponseWriter, r *http.Request) {
return
}

if os.Getenv("GO_ENV") == "testing" || os.Getenv("GO_ENV") == "staging" {
permission := models.Permissions{}
if err := permission.Set(user.ID); err != nil {
log.Println("Error setting permissions:", err)
}
} else {
events.EB.Publish("permissions", user)
}

userMap := map[string]interface{}{
"id": user.ID,
"name": user.Name,
Expand All @@ -67,8 +78,6 @@ func resetPassword(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)

events.EB.Publish("permissions", user)
}

func ResetPasswordRoute(router *mux.Router) {
Expand Down
15 changes: 12 additions & 3 deletions internal/routes/auth/signin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package auth

import (
"encoding/json"
"log"
"net/http"
"os"

"github.com/Tibz-Dankan/keep-active/internal/events"
"github.com/Tibz-Dankan/keep-active/internal/models"
Expand All @@ -16,7 +18,7 @@ func signIn(w http.ResponseWriter, r *http.Request) {

err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
services.AppError(err.Error(), 400, w)
services.AppError(err.Error(), 500, w)
return
}

Expand Down Expand Up @@ -50,6 +52,15 @@ func signIn(w http.ResponseWriter, r *http.Request) {
return
}

if os.Getenv("GO_ENV") == "testing" || os.Getenv("GO_ENV") == "staging" {
permission := models.Permissions{}
if err := permission.Set(user.ID); err != nil {
log.Println("Error setting permissions:", err)
}
} else {
events.EB.Publish("permissions", user)
}

userMap := map[string]interface{}{
"id": user.ID,
"name": user.Name,
Expand All @@ -66,8 +77,6 @@ func signIn(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)

events.EB.Publish("permissions", user)
}

func SignInRoute(router *mux.Router) {
Expand Down
20 changes: 14 additions & 6 deletions internal/routes/auth/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package auth

import (
"encoding/json"
"log"
"net/http"
"os"

"github.com/Tibz-Dankan/keep-active/internal/events"
"github.com/Tibz-Dankan/keep-active/internal/models"
Expand All @@ -15,7 +17,7 @@ func signUp(w http.ResponseWriter, r *http.Request) {

err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
services.AppError(err.Error(), 400, w)
services.AppError(err.Error(), 500, w)
return
}

Expand All @@ -35,8 +37,7 @@ func signUp(w http.ResponseWriter, r *http.Request) {
return
}

// TODO: To implement more scalable approach to set user roles
err = user.SetRole("client")
err = user.SetRole("user")
if err != nil {
services.AppError(err.Error(), 400, w)
return
Expand All @@ -55,6 +56,16 @@ func signUp(w http.ResponseWriter, r *http.Request) {
return
}

user.ID = userId
if os.Getenv("GO_ENV") == "testing" || os.Getenv("GO_ENV") == "staging" {
permission := models.Permissions{}
if err := permission.Set(user.ID); err != nil {
log.Println("Error setting permissions:", err)
}
} else {
events.EB.Publish("permissions", user)
}

newUser := map[string]interface{}{
"id": userId,
"name": user.Name,
Expand All @@ -71,9 +82,6 @@ func signUp(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(response)

user.ID = userId
events.EB.Publish("permissions", user)
}

func SignUpRoute(router *mux.Router) {
Expand Down
Loading

0 comments on commit a1c1581

Please sign in to comment.