-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
189 lines (147 loc) · 6.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"time"
"github.com/EnisMulic/Ask.it.Backend/constants"
"github.com/EnisMulic/Ask.it.Backend/controllers"
"github.com/EnisMulic/Ask.it.Backend/database"
"github.com/EnisMulic/Ask.it.Backend/middleware"
"github.com/EnisMulic/Ask.it.Backend/repositories"
"github.com/EnisMulic/Ask.it.Backend/services"
"github.com/EnisMulic/Ask.it.Backend/websockets"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
"github.com/rs/cors"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
err := godotenv.Load()
if err != nil {
log.Fatalf("Error loading .env file")
}
logger := log.New(os.Stdout, "ask.it.api", log.LstdFlags)
dsn := os.Getenv("CONNECTION_STRING")
db, dbErr := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if dbErr != nil {
log.Fatalf(dbErr.Error())
}
database.Migrate(db)
pool := websockets.NewPool()
go pool.Start()
userRepo := repositories.NewUserRepository(db)
questionRepo := repositories.NewQuestionRepository(db)
questionRatingRepo := repositories.NewUserQuestionRatingRepository(db)
answerRepo := repositories.NewAnswerRepository(db)
answerRatingRepo := repositories.NewUserAnswerRatingRepository(db)
answerNotificationRepo := repositories.NewAnswerNotificationRepository(db)
authSevice := services.NewAuthService(userRepo)
userService := services.NewUserService(userRepo, questionRepo)
questionService := services.NewQuestionService(questionRepo, questionRatingRepo, answerRepo, answerNotificationRepo, pool)
answerService := services.NewAnswerRepository(answerRepo, answerRatingRepo)
answerNotificationService := services.NewAnswerNotificationService(answerNotificationRepo)
ac := controllers.NewAuthController(logger, authSevice)
uc := controllers.NewUserController(logger, userService)
qc := controllers.NewQuestionController(logger, questionService)
answc := controllers.NewAnswerController(answerService)
answnc := controllers.NewAnswerNotificationController(answerNotificationService)
r := mux.NewRouter().StrictSlash(true)
nh := websockets.NewNotificationHandler()
r.HandleFunc(constants.NotificationRoute, func(w http.ResponseWriter, r *http.Request) {
nh.ServeWS(pool, w, r)
})
userGetRouter := r.Methods(http.MethodGet).Subrouter()
userGetRouter.HandleFunc(constants.GetMeRoute, uc.GetMe)
userGetRouter.Use(middleware.IsAuthorized)
userGetRouter.Use(middleware.AddContentType)
// auth routers
authPostRouter := r.Methods(http.MethodPost).Subrouter()
authPostRouter.Use(middleware.AddContentType)
authPostRouter.HandleFunc(constants.LoginRoute, ac.Login)
authPostRouter.HandleFunc(constants.RegisterRoute, ac.Register)
// users routers
usersGetRouter := r.Methods(http.MethodGet).Subrouter()
usersGetRouter.HandleFunc(constants.GetUsersRoute, uc.Get)
usersGetRouter.HandleFunc(constants.GetUserByIdRoute, uc.GetById)
usersGetRouter.HandleFunc(constants.GetUsersQuestionsRoute, uc.GetQuestions)
usersGetRouter.HandleFunc(constants.GetTopUsersRoute, uc.GetTop)
usersGetRouter.Use(middleware.AddContentType)
usersPostRoutes := r.Methods(http.MethodPost).Subrouter()
usersPostRoutes.HandleFunc(constants.ChangeUserPasswordRoute, uc.ChangePassword)
usersPostRoutes.HandleFunc(constants.UpdateUserRoute, uc.Update)
usersPostRoutes.Use(middleware.AddContentType)
usersPostRoutes.Use(middleware.IsAuthorized)
// questions routers
questionsGetRouter := r.Methods(http.MethodGet).Subrouter()
questionsGetRouter.HandleFunc(constants.GetQuestionsRoute, qc.Get)
questionsGetRouter.HandleFunc(constants.GetQuestionByIdRoute, qc.GetById)
questionsGetRouter.HandleFunc(constants.GetHotQuestionsRoute, qc.GetHot)
questionsGetRouter.Use(middleware.AddContentType)
questionsPostRouter := r.Methods(http.MethodPost).Subrouter()
questionsPostRouter.HandleFunc(constants.CreateQuestionRoute, qc.Create)
questionsPostRouter.HandleFunc(constants.CreateQuestionAnswerRoute, qc.CreateAnswer)
questionsPostRouter.HandleFunc(constants.LikeQuestionRoute, qc.Like)
questionsPostRouter.HandleFunc(constants.LikeQuestionUndoRoute, qc.LikeUndo)
questionsPostRouter.HandleFunc(constants.DislikeQuestionRoute, qc.Dislike)
questionsPostRouter.HandleFunc(constants.DislikeQuestionUndoRoute, qc.DislikeUndo)
questionsPostRouter.Use(middleware.AddContentType)
questionsPostRouter.Use(middleware.IsAuthorized)
questionsDeleteRouter := r.Methods(http.MethodDelete).Subrouter()
questionsDeleteRouter.HandleFunc(constants.DeleteQuestionRoute, qc.Delete)
questionsDeleteRouter.Use(middleware.AddContentType)
questionsDeleteRouter.Use(middleware.IsAuthorized)
// answer routers
answerPostRouter := r.Methods(http.MethodPost).Subrouter()
answerPostRouter.HandleFunc(constants.LikeAnswerRoute, answc.Like)
answerPostRouter.HandleFunc(constants.LikeAnswerUndoRoute, answc.LikeUndo)
questionsPostRouter.HandleFunc(constants.DislikeAnswerRoute, answc.Dislike)
questionsPostRouter.HandleFunc(constants.DislikeAnswerUndoRoute, answc.DislikeUndo)
questionsPostRouter.Use(middleware.AddContentType)
questionsPostRouter.Use(middleware.IsAuthorized)
answerPutRouter := r.Methods(http.MethodPut).Subrouter()
answerPutRouter.HandleFunc(constants.UpdateAnswerRoute, answc.Update)
answerPutRouter.Use(middleware.AddContentType)
answerPutRouter.Use(middleware.IsAuthorized)
answerDeleteRouter := r.Methods(http.MethodDelete).Subrouter()
answerDeleteRouter.HandleFunc(constants.DeleteAnswerRoute, answc.Delete)
answerDeleteRouter.Use(middleware.AddContentType)
answerDeleteRouter.Use(middleware.IsAuthorized)
// answer notification routers
answerNotificationPostRouter := r.Methods(http.MethodPost).Subrouter()
answerNotificationPostRouter.HandleFunc(constants.MarkReadAnswerNotificationRoute, answnc.MarkRead)
answerNotificationPostRouter.Use(middleware.AddContentType)
answerNotificationPostRouter.Use(middleware.IsAuthorized)
r.PathPrefix("/swagger/").Handler(http.StripPrefix("/swagger/", http.FileServer(http.Dir("./swaggerui/"))))
cors := cors.New(cors.Options{
AllowedOrigins: []string{os.Getenv("CLIENT_APP")},
AllowCredentials: true,
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
})
addr := os.Getenv("API_ADDRESS")
srv := &http.Server {
Handler: cors.Handler(r),
Addr: addr,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
go func() {
err := srv.ListenAndServe()
if err != nil {
logger.Fatal(err)
}
}()
signalChannel := make(chan os.Signal, 1)
signal.Notify(signalChannel, os.Interrupt)
signal := <-signalChannel
log.Println("Got signal:", signal)
ctx, erro := context.WithTimeout(context.Background(), 30*time.Second)
if erro != nil {
log.Fatal(erro)
}
srv.Shutdown(ctx)
}