add jwt authentication, and fix cours for next js
parent
3026f89f2e
commit
05b8d55d0e
|
@ -7,4 +7,4 @@ log_level: "debug"
|
|||
|
||||
# db
|
||||
DB:
|
||||
baseurlbd: "host=localhost:7000 user=films password=5429593sS dbname=postgres sslmode=disable"
|
||||
baseurlbd: ""
|
3
go.mod
3
go.mod
|
@ -5,7 +5,9 @@ go 1.19
|
|||
require github.com/sirupsen/logrus v1.9.0
|
||||
|
||||
require (
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0-rc.2 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
|
@ -15,6 +17,7 @@ require (
|
|||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/puddle v1.3.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.0 // indirect
|
||||
github.com/rs/cors v1.9.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
)
|
||||
|
||||
|
|
6
go.sum
6
go.sum
|
@ -7,6 +7,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
|
|||
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/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
|
@ -14,6 +16,8 @@ github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
|
|||
github.com/golang-jwt/jwt/v5 v5.0.0-rc.2 h1:hXPcSazn8wKOfSb9y2m1bdgUMlDxVDarxh3lJVbC6JE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0-rc.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
|
@ -101,6 +105,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
|
||||
github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
|
|
|
@ -13,6 +13,7 @@ type Bd struct {
|
|||
filmsrepo *Filmsrepo
|
||||
siriesrepo *Siriesrepo
|
||||
userrepo *Userrepo
|
||||
tokenrepo *Tokenrepo
|
||||
}
|
||||
|
||||
func New(config *ConfigBD) *Bd {
|
||||
|
@ -68,3 +69,13 @@ func (b *Bd) User() *Userrepo {
|
|||
}
|
||||
return b.userrepo
|
||||
}
|
||||
|
||||
func (b *Bd) Token() *Tokenrepo {
|
||||
if b.tokenrepo != nil {
|
||||
return b.tokenrepo
|
||||
}
|
||||
b.tokenrepo = &Tokenrepo{
|
||||
db: *b,
|
||||
}
|
||||
return b.tokenrepo
|
||||
}
|
||||
|
|
|
@ -5,6 +5,14 @@ type User struct {
|
|||
Login string `json:"login"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Avatar_Url string
|
||||
Avatar_Url *string
|
||||
AccesToken string
|
||||
PermisionLVL int
|
||||
}
|
||||
|
||||
type UserData struct {
|
||||
Login string
|
||||
Email string
|
||||
PermisionLVL int
|
||||
AccesToken string
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package bd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Tokenrepo struct {
|
||||
db Bd
|
||||
}
|
||||
|
||||
func (t *Tokenrepo) Create(login string, refreshToken string) error {
|
||||
sql := fmt.Sprint("INSERT INTO tokens (login, refreshtoken) VALUES($1, $2)")
|
||||
_, err := t.db.db.Exec(context.Background(), sql, login, refreshToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Tokenrepo) FindByLogin(login string) (*string, error) {
|
||||
var refreshToken string
|
||||
sql := fmt.Sprint("Select refreshtoken from tokens WHERE login = $1")
|
||||
rows, err := t.db.db.Query(context.Background(), sql, login)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&refreshToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &refreshToken, nil
|
||||
|
||||
}
|
||||
|
||||
func (t *Tokenrepo) FindByToken(token string) (*string, error) {
|
||||
var login string
|
||||
sql := fmt.Sprint("Select login from tokens WHERE refreshtoken = $1")
|
||||
rows, err := t.db.db.Query(context.Background(), sql, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&login)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &login, nil
|
||||
}
|
||||
|
||||
func (t *Tokenrepo) DeleteByLogin(login string) error {
|
||||
sql := fmt.Sprint("DELETE FROM tokens WHERE login = $1")
|
||||
_, err := t.db.db.Exec(context.Background(), sql, login)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -12,8 +12,8 @@ type Userrepo struct {
|
|||
}
|
||||
|
||||
func (u *Userrepo) Create(user *model.User) error {
|
||||
_, err := u.db.db.Exec(context.Background(),
|
||||
"INSERT INTO users (login, email, password, permisionlvl) VALUES($1, $2, $3, $4)", user.Login, user.Email, user.Password, user.PermisionLVL)
|
||||
sql := fmt.Sprint("INSERT INTO users (login, email, password, permisionlvl) VALUES($1, $2, $3, $4)")
|
||||
_, err := u.db.db.Exec(context.Background(), sql, user.Login, user.Email, user.Password, user.PermisionLVL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -60,6 +60,18 @@ func (u *Userrepo) FindByEmail(email string) (*model.User, error) {
|
|||
|
||||
}
|
||||
|
||||
func (u *Userrepo) FindByAll() (*model.User, error) {
|
||||
return nil, nil
|
||||
func (u *Userrepo) FindByLoginPas(login string) (*model.User, error) {
|
||||
var user model.User
|
||||
rows, err := u.db.db.Query(context.Background(), "SELECT login, password, permisionlvl, email FROM users WHERE login = $1", login)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&user.Login, &user.Password, &user.PermisionLVL, &user.Email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ import (
|
|||
|
||||
func (r *RestServer) configureRouterFilms() {
|
||||
r.router.HandleFunc("/api/hello", r.HandleHello()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films", r.HendleFindAll()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/{id:[0-9]+}", r.HendleFindID()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/{name}", r.HeandleFilmsFindName()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/genres/{name}", r.HeandleFilmsSortGenres()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/page/{page:[0-9]+}", r.HendlePagination()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/last/", r.HeadleGetLastItem()).Methods("GET")
|
||||
r.router.HandleFunc("/api/films", r.checkJwtAccess(r.HendleFindAll())).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/{id:[0-9]+}", r.checkJwtAccess(r.HendleFindID())).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/{name}", r.checkJwtAccess(r.HeandleFilmsFindName())).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/genres/{name}", r.checkJwtAccess(r.HeandleFilmsSortGenres())).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/page/{page:[0-9]+}", r.checkJwtAccess(r.HendlePagination())).Methods("GET")
|
||||
r.router.HandleFunc("/api/films/last/", r.checkJwtAccess(r.HeadleGetLastItem())).Methods("GET")
|
||||
}
|
||||
|
||||
func (r *RestServer) HandleHello() http.HandlerFunc {
|
||||
|
@ -64,10 +64,6 @@ func (r *RestServer) HendleFindAll() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeandleFilmsFindName() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
name := mux.Vars(res)["name"]
|
||||
films, err := r.db.Films().FindByName(name)
|
||||
if err != nil {
|
||||
|
@ -88,9 +84,6 @@ func (r *RestServer) HeandleFilmsFindName() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeandleFilmsSortGenres() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
name := mux.Vars(res)["name"]
|
||||
films, err := r.db.Films().SortByGanres(name)
|
||||
if err != nil {
|
||||
|
@ -106,9 +99,6 @@ func (r *RestServer) HeandleFilmsSortGenres() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HendleFindID() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
id := mux.Vars(res)["id"]
|
||||
fmt.Println(mux.Vars(res))
|
||||
film, err := r.db.Films().FindById(id)
|
||||
|
@ -126,9 +116,6 @@ func (r *RestServer) HendleFindID() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HendlePagination() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
id := mux.Vars(res)["page"]
|
||||
films, err := r.db.Films().Pagination(id)
|
||||
if err != nil {
|
||||
|
@ -145,9 +132,6 @@ func (r *RestServer) HendlePagination() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeadleGetLastItem() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
films, err := r.db.Films().LastItem()
|
||||
if err != nil {
|
||||
r.logger.Errorln(err)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package restserver
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/pkg/utils/jwt"
|
||||
)
|
||||
|
||||
func (r *RestServer) checkJwtAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
str := res.Header.Values("Authorization")
|
||||
if str == nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Ошибка Авторизации"}`)
|
||||
return
|
||||
}
|
||||
|
||||
token := strings.Split(str[0], " ")
|
||||
chek, err := jwt.ValidateToken(token[1], []byte(os.Getenv("JWT_SECRET_KEY_ACCESS")))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Ошибка Авторизации"}`)
|
||||
r.logger.Error(err)
|
||||
return
|
||||
}
|
||||
if chek {
|
||||
next(w, res)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Ошибка Авторизации"}`)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/internal/bd"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/cors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -37,14 +38,19 @@ func (r *RestServer) Start() error {
|
|||
if err := r.configurebd(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
corsHendler := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"http://localhost:3000"},
|
||||
AllowedHeaders: []string{"Content-Type", "Authorization", "Set-Cookie"},
|
||||
AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodOptions, http.MethodDelete, http.MethodPut},
|
||||
AllowCredentials: true,
|
||||
}).Handler(r.router)
|
||||
r.configureRouterFilms()
|
||||
r.configureRouterSiries()
|
||||
r.configureRouterUser()
|
||||
|
||||
r.logger.Info("Starting Server")
|
||||
r.logger.Info("Listen server on ", r.config.BindPort, " Port")
|
||||
return http.ListenAndServe(r.config.BindPort, r.router)
|
||||
return http.ListenAndServe(r.config.BindPort, corsHendler)
|
||||
}
|
||||
|
||||
func (r *RestServer) configureLogger() error {
|
||||
|
|
|
@ -12,20 +12,17 @@ import (
|
|||
)
|
||||
|
||||
func (r *RestServer) configureRouterSiries() {
|
||||
r.router.HandleFunc("/api/siries", r.HendleFindAllSiries()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/{id:[0-9]+}", r.HendleFindIDSiries()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/{name}", r.HeandleSiriesFindName()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/genres/{name}", r.HeandleSiriesSortGenres()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/page/{page:[0-9]+}", r.HendlePaginationSiries()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/lastS/", r.HeadleGetLastItemSiries()).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries", r.checkJwtAccess(r.HendleFindAllSiries())).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/{id:[0-9]+}", r.checkJwtAccess(r.HendleFindIDSiries())).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/{name}", r.checkJwtAccess(r.HeandleSiriesFindName())).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/genres/{name}", r.checkJwtAccess(r.HeandleSiriesSortGenres())).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/page/{page:[0-9]+}", r.checkJwtAccess(r.HendlePaginationSiries())).Methods("GET")
|
||||
r.router.HandleFunc("/api/siries/lastS/", r.checkJwtAccess(r.HeadleGetLastItemSiries())).Methods("GET")
|
||||
}
|
||||
|
||||
func (r *RestServer) HandleHelloSiries() http.HandlerFunc {
|
||||
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
id := res.URL.Query().Get("id")
|
||||
fmt.Println(id)
|
||||
cout, err := r.db.Siries().GetCountFilms()
|
||||
|
@ -63,9 +60,6 @@ func (r *RestServer) HendleFindAllSiries() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeandleSiriesFindName() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
name := mux.Vars(res)["name"]
|
||||
siries, err := r.db.Siries().FindByName(name)
|
||||
if err != nil {
|
||||
|
@ -86,9 +80,6 @@ func (r *RestServer) HeandleSiriesFindName() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeandleSiriesSortGenres() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
name := mux.Vars(res)["name"]
|
||||
siries, err := r.db.Siries().SortByGanres(name)
|
||||
if err != nil {
|
||||
|
@ -104,9 +95,6 @@ func (r *RestServer) HeandleSiriesSortGenres() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HendleFindIDSiries() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
id := mux.Vars(res)["id"]
|
||||
fmt.Println(mux.Vars(res))
|
||||
siries, err := r.db.Siries().FindById(id)
|
||||
|
@ -123,9 +111,6 @@ func (r *RestServer) HendleFindIDSiries() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HendlePaginationSiries() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
id := mux.Vars(res)["page"]
|
||||
siries, err := r.db.Siries().Pagination(id)
|
||||
if err != nil {
|
||||
|
@ -142,9 +127,6 @@ func (r *RestServer) HendlePaginationSiries() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HeadleGetLastItemSiries() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
siries, err := r.db.Siries().LastItem()
|
||||
if err != nil {
|
||||
r.logger.Errorln(err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package restserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -11,8 +12,9 @@ import (
|
|||
|
||||
func (r *RestServer) configureRouterUser() {
|
||||
r.router.HandleFunc("/api/register", r.chekUserRegistr(r.HandleFuncRegUser())).Methods("POST")
|
||||
r.router.HandleFunc("/api/login", r.HandleFuncLoginUser()).Methods("POST")
|
||||
r.router.HandleFunc("/api/logout", r.HandleFuncLogOutUser()).Methods("POST")
|
||||
r.router.HandleFunc("/api/login", r.chekUserLogin(r.HandleFuncLoginUser())).Methods("POST")
|
||||
r.router.HandleFunc("/api/logout", r.chekUserLogout(r.HandleFuncLogOutUser())).Methods("GET")
|
||||
r.router.HandleFunc("/api/refresh", r.checkUserRefresh(r.HandleFuncRefresh())).Methods("GET")
|
||||
}
|
||||
|
||||
func (r *RestServer) HandleFuncRegUser() http.HandlerFunc {
|
||||
|
@ -29,7 +31,27 @@ func (r *RestServer) HandleFuncRegUser() http.HandlerFunc {
|
|||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
} else {
|
||||
io.WriteString(w, `{"data":"Пользователь создан"}`)
|
||||
// Reftoken, err := r.db.Token().FindByLogin(users.Login)
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
// if Reftoken != nil {
|
||||
// users.RefreshToken = *Reftoken
|
||||
// } else {
|
||||
// r.db.Token().Create(users.Login, users.RefreshToken)
|
||||
// }
|
||||
|
||||
// data := &model.UserData{
|
||||
// Email: users.Email,
|
||||
// PermisionLVL: users.PermisionLVL,
|
||||
// AccesToken: users.AccesToken,
|
||||
// RefreshToken: users.RefreshToken,
|
||||
// }
|
||||
// err = json.NewEncoder(w).Encode(data)
|
||||
// if err != nil {
|
||||
// r.logger.Errorln(err)
|
||||
// }
|
||||
io.WriteString(w, `{"data":"Пользователь успешно зарегистрирован"}`)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,12 +60,40 @@ func (r *RestServer) HandleFuncRegUser() http.HandlerFunc {
|
|||
|
||||
func (r *RestServer) HandleFuncLoginUser() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
fmt.Println("login")
|
||||
users := res.Context().Value(ContextKeyUser).(*model.User)
|
||||
data := &model.UserData{
|
||||
Login: users.Login,
|
||||
Email: users.Email,
|
||||
PermisionLVL: users.PermisionLVL,
|
||||
AccesToken: users.AccesToken,
|
||||
}
|
||||
err := json.NewEncoder(w).Encode(data)
|
||||
if err != nil {
|
||||
r.logger.Errorln(err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestServer) HandleFuncLogOutUser() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
fmt.Println("login")
|
||||
fmt.Println("Logout")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestServer) HandleFuncRefresh() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
users := res.Context().Value(ContextKeyUser).(*model.User)
|
||||
data := &model.UserData{
|
||||
Login: users.Login,
|
||||
Email: users.Email,
|
||||
PermisionLVL: users.PermisionLVL,
|
||||
AccesToken: users.AccesToken,
|
||||
}
|
||||
err := json.NewEncoder(w).Encode(data)
|
||||
if err != nil {
|
||||
r.logger.Errorln(err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,12 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/internal/bd/model"
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/pkg/utils/jwt"
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/pkg/utils/password"
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/pkg/utils/validator"
|
||||
)
|
||||
|
||||
|
@ -21,6 +25,9 @@ func (r *RestServer) chekUserRegistr(next http.HandlerFunc) http.HandlerFunc {
|
|||
err := json.NewDecoder(res.Body).Decode(users)
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
io.WriteString(w, `{"data":"Что-то пошло не так"}`)
|
||||
return
|
||||
}
|
||||
user, err := r.db.User().FindByLogin(users.Login)
|
||||
if err != nil {
|
||||
|
@ -44,6 +51,133 @@ func (r *RestServer) chekUserRegistr(next http.HandlerFunc) http.HandlerFunc {
|
|||
io.WriteString(w, fmt.Sprintf(`{"data":"%s"}`, err))
|
||||
return
|
||||
}
|
||||
users.PermisionLVL = defaultPermLvl
|
||||
// jwtToken, _ := jwt.GenerateTokens(*users)
|
||||
|
||||
// cookie := http.Cookie{
|
||||
// Name: "refreshToken",
|
||||
// Value: jwtToken.RefreshToken,
|
||||
// Expires: time.Now().Add(time.Hour * 24 * 360),
|
||||
// HttpOnly: true,
|
||||
// }
|
||||
// http.SetCookie(w, &cookie)
|
||||
// users.AccesToken = jwtToken.AccesToken
|
||||
// users.RefreshToken = jwtToken.RefreshToken
|
||||
next(w, res.WithContext(context.WithValue(res.Context(), ContextKeyUser, users)))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestServer) chekUserLogin(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
users := &model.User{}
|
||||
err := json.NewDecoder(res.Body).Decode(users)
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Что-то пошло не так"}`)
|
||||
return
|
||||
}
|
||||
user, err := r.db.User().FindByLoginPas(users.Login)
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Что-то пошло не так"}`)
|
||||
return
|
||||
}
|
||||
if user.Login == "" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Неверный логин или пароль"}`)
|
||||
return
|
||||
}
|
||||
checkPass := password.CheckValid(users.Password, user.Password)
|
||||
if !checkPass {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
io.WriteString(w, `{"data":"Неверный логин или пароль"}`)
|
||||
return
|
||||
}
|
||||
jwtToken, _ := jwt.GenerateTokens(*user)
|
||||
Reftoken, err := r.db.Token().FindByLogin(users.Login)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
io.WriteString(w, `{"data":"Что-то пошло не так "}`)
|
||||
return
|
||||
}
|
||||
if *Reftoken != "" {
|
||||
jwtToken.RefreshToken = *Reftoken
|
||||
} else {
|
||||
r.db.Token().Create(users.Login, jwtToken.RefreshToken)
|
||||
}
|
||||
cookie := http.Cookie{
|
||||
Name: "refreshToken",
|
||||
Value: jwtToken.RefreshToken,
|
||||
Path: "/",
|
||||
SameSite: http.SameSiteDefaultMode,
|
||||
Expires: time.Now().Add(time.Hour * 24 * 360),
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, &cookie)
|
||||
users.AccesToken = jwtToken.AccesToken
|
||||
users.PermisionLVL = user.PermisionLVL
|
||||
users.Email = user.Email
|
||||
next(w, res.WithContext(context.WithValue(res.Context(), ContextKeyUser, users)))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestServer) chekUserLogout(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
checkCookie, err := res.Cookie("refreshToken")
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
} else {
|
||||
if checkCookie.Value != "" {
|
||||
login, _ := r.db.Token().FindByToken(checkCookie.Value)
|
||||
if *login != "" {
|
||||
r.db.Token().DeleteByLogin(*login)
|
||||
}
|
||||
cookie := http.Cookie{
|
||||
Name: "refreshToken",
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, &cookie)
|
||||
}
|
||||
}
|
||||
|
||||
next(w, res)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestServer) checkUserRefresh(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, res *http.Request) {
|
||||
users := &model.User{}
|
||||
checkCookie, err := res.Cookie("refreshToken")
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
chekToken, err := jwt.ValidateToken(checkCookie.Value, []byte(os.Getenv("JWT_SECRET_KEY_REFRESH")))
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
login, err := r.db.Token().FindByToken(checkCookie.Value)
|
||||
if err != nil {
|
||||
r.logger.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if *login != "" && chekToken {
|
||||
userdb, _ := r.db.User().FindByLoginPas(*login)
|
||||
jwtToken, _ := jwt.GenerateTokens(*userdb)
|
||||
users.Login = userdb.Login
|
||||
users.AccesToken = jwtToken.AccesToken
|
||||
users.PermisionLVL = userdb.PermisionLVL
|
||||
users.Email = userdb.Email
|
||||
next(w, res.WithContext(context.WithValue(res.Context(), ContextKeyUser, users)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,15 @@ CREATE TABLE films (
|
|||
iframe_src VARCHAR(2000),
|
||||
ratingImdbVoteCount INTEGER,
|
||||
ratingKinopoiskVoteCount INTEGER,
|
||||
created VARCHAR(1500),
|
||||
created VARCHAR(1000),
|
||||
content_type VARCHAR(25),
|
||||
ratingAgeLimits VARCHAR(25),
|
||||
media JSON,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
|
||||
|
||||
CREATE TABLE users (
|
||||
id SERIAL,
|
||||
login TEXT not NULL,
|
||||
|
@ -34,8 +38,32 @@ CREATE TABLE users (
|
|||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE Siries (
|
||||
id INTEGER NOT NULL,
|
||||
ru_title VARCHAR(256),
|
||||
orig_title VARCHAR(255),
|
||||
imdb_id VARCHAR(255),
|
||||
kinopoisk_id INTEGER,
|
||||
posterUrl VARCHAR(1500),
|
||||
posterUrlPreview VARCHAR(1500),
|
||||
countries JSON,
|
||||
genres JSON,
|
||||
year INTEGER,
|
||||
description VARCHAR(20000),
|
||||
ratingKinopoisk INTEGER,
|
||||
ratingImdb INTEGER,
|
||||
iframe_src VARCHAR(2000),
|
||||
ratingImdbVoteCount INTEGER,
|
||||
ratingKinopoiskVoteCount INTEGER,
|
||||
created VARCHAR(1000),
|
||||
content_type VARCHAR(25),
|
||||
ratingAgeLimits VARCHAR(25),
|
||||
translation JSON,
|
||||
episodes JSON,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
CREATE TABLE tokens (
|
||||
userID INTEGER NOT NULL,
|
||||
refreshToken TEXT NOT NULL
|
||||
login TEXT NOT NULL,
|
||||
refreshToken TEXT NOT NULL,
|
||||
PRIMARY KEY(login)
|
||||
);
|
|
@ -0,0 +1,24 @@
|
|||
package jwt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
func ValidateToken(tokenString string, secretKey []byte) (bool, error) {
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return secretKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package jwt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.ukamnya.ru/stulyaganov/RestApiv2/internal/bd/model"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type jwtToken struct {
|
||||
AccesToken string
|
||||
RefreshToken string
|
||||
}
|
||||
|
||||
func GenerateTokens(payload model.User) (*jwtToken, error) {
|
||||
AccessKey := os.Getenv("JWT_SECRET_KEY_ACCESS")
|
||||
RefreshKey := os.Getenv("JWT_SECRET_KEY_REFRESH")
|
||||
claimsAccess := jwt.MapClaims{
|
||||
"name": payload.Login,
|
||||
"permisionlvl": payload.PermisionLVL,
|
||||
"email": payload.Email,
|
||||
"exp": time.Now().Add(time.Hour * 24 * 60).Unix(),
|
||||
}
|
||||
claimsRefresh := jwt.MapClaims{
|
||||
"name": payload.Login,
|
||||
"permisionlvl": payload.PermisionLVL,
|
||||
"email": payload.Email,
|
||||
"exp": time.Now().Add(time.Hour * 24 * 360).Unix(),
|
||||
}
|
||||
|
||||
tokenAcc := jwt.NewWithClaims(jwt.SigningMethodHS256, claimsAccess)
|
||||
tokenRef := jwt.NewWithClaims(jwt.SigningMethodHS256, claimsRefresh)
|
||||
|
||||
AccesToken, err := tokenAcc.SignedString([]byte(AccessKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
RefreshToken, err := tokenRef.SignedString([]byte(RefreshKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &jwtToken{
|
||||
AccesToken: AccesToken,
|
||||
RefreshToken: RefreshToken,
|
||||
}, nil
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package password
|
||||
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (*[]byte, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
|
@ -9,3 +11,12 @@ func HashPassword(password string) (*[]byte, error) {
|
|||
}
|
||||
return &bytes, err
|
||||
}
|
||||
|
||||
func CheckValid(password string, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue