This commit is contained in:
42
.gitignore
vendored
42
.gitignore
vendored
@ -1,2 +1,44 @@
|
|||||||
blog.db
|
blog.db
|
||||||
|
backend
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
web/dist
|
||||||
|
web/tmp
|
||||||
|
web/out-tsc
|
||||||
|
web/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
web/node_modules
|
||||||
|
web/npm-debug.log
|
||||||
|
web/yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
web/.idea/
|
||||||
|
web/.project
|
||||||
|
web/.classpath
|
||||||
|
web/.c9/
|
||||||
|
web/*.launch
|
||||||
|
web/.settings/
|
||||||
|
web/*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
web/.vscode/*
|
||||||
|
web/!.vscode/settings.json
|
||||||
|
web/!.vscode/tasks.json
|
||||||
|
web/!.vscode/launch.json
|
||||||
|
web/!.vscode/extensions.json
|
||||||
|
web/.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
web/.angular/cache
|
||||||
|
web/.sass-cache/
|
||||||
|
web/connect.lock
|
||||||
|
web/coverage
|
||||||
|
web/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
web/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
web/Thumbs.db
|
||||||
|
@ -50,6 +50,45 @@ func (s *Service) Signup(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signup handles user signup by decoding request body, hashing the password, and saving user data to the database.
|
||||||
|
func (s *Service) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var err error
|
||||||
|
var login Login
|
||||||
|
var password []byte
|
||||||
|
|
||||||
|
claims, ok := ExtractClaims(r.Context())
|
||||||
|
if !ok {
|
||||||
|
log.Println("Error while extracting claims")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.NewDecoder(r.Body).Decode(&login); err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len([]byte(login.Password)) > 72 {
|
||||||
|
fmt.Fprint(w, "Password to long, max 72 bytes")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if password, err = bcrypt.GenerateFromPassword([]byte(login.Password), 6); err != nil {
|
||||||
|
log.Println("Error: ", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.db.Model(&model.User{}).Where("id = ?", claims.UserID).Update("password", password).Error
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
log.Printf("Error: %v", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
// Login handles user login by decoding request body, verifying credentials, and returning a JWT token.
|
// Login handles user login by decoding request body, verifying credentials, and returning a JWT token.
|
||||||
func (s *Service) Login(w http.ResponseWriter, r *http.Request) {
|
func (s *Service) Login(w http.ResponseWriter, r *http.Request) {
|
||||||
var login Login
|
var login Login
|
||||||
|
@ -19,9 +19,7 @@ func CreateMux(cfg *config.Config) (r *mux.Router) {
|
|||||||
r.Use(cors.HandlerForOrigin("*"))
|
r.Use(cors.HandlerForOrigin("*"))
|
||||||
|
|
||||||
app(r.PathPrefix("/api").Subrouter(), cfg)
|
app(r.PathPrefix("/api").Subrouter(), cfg)
|
||||||
|
frontend(r.PathPrefix("/"))
|
||||||
frontend := web.Frontend
|
|
||||||
r.PathPrefix("/").Handler(middlewares.AddPrefix("/dist/frontend/browser", http.FileServerFS(frontend)))
|
|
||||||
|
|
||||||
r.Methods("OPTIONS").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
r.Methods("OPTIONS").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// The CORS middleware should set up the headers for you
|
// The CORS middleware should set up the headers for you
|
||||||
@ -31,15 +29,28 @@ func CreateMux(cfg *config.Config) (r *mux.Router) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func frontend(r *mux.Route) {
|
||||||
|
frontend := web.Frontend
|
||||||
|
r.Handler(
|
||||||
|
middlewares.AddPrefix("/dist/frontend/browser",
|
||||||
|
middlewares.FallbackFile(
|
||||||
|
frontend,
|
||||||
|
"/dist/frontend/browser/index.html",
|
||||||
|
http.FileServerFS(frontend),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
func app(r *mux.Router, cfg *config.Config) {
|
func app(r *mux.Router, cfg *config.Config) {
|
||||||
db := model.Init()
|
db := model.Init()
|
||||||
blg := posts.New(db)
|
blg := posts.New(db)
|
||||||
auth := auth.New(&cfg.Auth, db)
|
auth := auth.New(&cfg.Auth, db)
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
r.HandleFunc("/login", auth.Login).Methods("POST")
|
r.HandleFunc("/auth/login", auth.Login).Methods("POST")
|
||||||
r.HandleFunc("/signup", auth.Signup).Methods("POST")
|
r.HandleFunc("/auth/signup", auth.Signup).Methods("POST")
|
||||||
r.Handle("/logout", auth.Authenticated(auth.Logout)).Methods("DELETE")
|
r.Handle("/auth/password", auth.Authenticated(auth.ChangePassword)).Methods("PUT")
|
||||||
|
r.Handle("/auth/logout", auth.Authenticated(auth.Logout)).Methods("DELETE")
|
||||||
|
|
||||||
// Posts
|
// Posts
|
||||||
r.Handle("/posts", auth.Authenticated(blg.SavePost, model.RoleUser, model.RoleAdmin)).Methods("POST")
|
r.Handle("/posts", auth.Authenticated(blg.SavePost, model.RoleUser, model.RoleAdmin)).Methods("POST")
|
||||||
|
61
pkg/middlewares/fallback.go
Normal file
61
pkg/middlewares/fallback.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package middlewares
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FallbackFile serves a fallback file if the next handler returns a 404.
|
||||||
|
// fs: The file system to serve the fallback file from.
|
||||||
|
// name: The name of the fallback file.
|
||||||
|
// next: The next handler to serve.
|
||||||
|
func FallbackFile(fs fs.FS, name string, next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
bw := &buffedResponseWriter{
|
||||||
|
w,
|
||||||
|
0,
|
||||||
|
bytes.NewBuffer([]byte{}),
|
||||||
|
}
|
||||||
|
next.ServeHTTP(bw, r)
|
||||||
|
|
||||||
|
if bw.statusCode == http.StatusNotFound {
|
||||||
|
bw.Clear()
|
||||||
|
|
||||||
|
http.ServeFileFS(bw, r, fs, name)
|
||||||
|
bw.WriteHeader(http.StatusOK)
|
||||||
|
bw.Header().Add("Content-Type", "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
bw.Apply()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type buffedResponseWriter struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
statusCode int
|
||||||
|
buff *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buffedResponseWriter) WriteHeader(code int) {
|
||||||
|
b.statusCode = code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buffedResponseWriter) Write(p []byte) (int, error) {
|
||||||
|
return b.buff.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buffedResponseWriter) Clear() {
|
||||||
|
b.buff.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buffedResponseWriter) Apply() {
|
||||||
|
_, err := b.ResponseWriter.Write(b.buff.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while applying buffedResponseWriter: ", err)
|
||||||
|
b.ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
if b.statusCode != 200 {
|
||||||
|
b.ResponseWriter.WriteHeader(b.statusCode)
|
||||||
|
}
|
||||||
|
}
|
@ -73,11 +73,11 @@ export class AuthService {
|
|||||||
|
|
||||||
login(user: User) {
|
login(user: User) {
|
||||||
this.http
|
this.http
|
||||||
.post<LoginResponse>(`${environment.apiRoot}/login`, user)
|
.post<LoginResponse>(`${environment.apiRoot}/auth/login`, user)
|
||||||
.subscribe((res) => this.jwt.set(res.token));
|
.subscribe((res) => this.jwt.set(res.token));
|
||||||
}
|
}
|
||||||
logout() {
|
logout() {
|
||||||
this.http.delete(`${environment.apiRoot}/logout`).subscribe(() => {
|
this.http.delete(`${environment.apiRoot}/auth/logout`).subscribe(() => {
|
||||||
this.jwt.set(null);
|
this.jwt.set(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user