feat: added activity log
This commit is contained in:
@@ -26,18 +26,21 @@ func APIRegister(w http.ResponseWriter, r *http.Request) {
|
||||
var user models.User
|
||||
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
|
||||
log.Println("POST [api/register] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", "", "auth.register.failed", "auth", "", "Invalid request body", http.StatusBadRequest)
|
||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if user.Username == "" || user.Password == "" {
|
||||
log.Println("POST [api/register] " + r.RemoteAddr + ": Username or Password is empty")
|
||||
RecordActivity(r, "", strings.ToLower(strings.TrimSpace(user.Username)), "auth.register.failed", "auth", "", "Username and password required", http.StatusBadRequest)
|
||||
http.Error(w, "username and password required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(user.Password) > 72 {
|
||||
log.Println("POST [api/register] User password too long")
|
||||
RecordActivity(r, "", strings.ToLower(strings.TrimSpace(user.Username)), "auth.register.failed", "auth", "", "Password exceeds maximum length", http.StatusUnprocessableEntity)
|
||||
http.Error(w, "Password exceeds the maximum allowed length of 72 characters", http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
@@ -54,10 +57,12 @@ func APIRegister(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err := storage.AddUser(&user); err != nil {
|
||||
log.Println("POST [api/register] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", strings.ToLower(strings.TrimSpace(user.Username)), "auth.register.failed", "auth", "", "User already exists or could not be created", http.StatusBadRequest)
|
||||
http.Error(w, "user already exists", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
RecordActivity(r, user.ID, strings.ToLower(strings.TrimSpace(user.Username)), "auth.register.succeeded", "auth", "", "User registered", http.StatusCreated)
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
log.Println("POST [api/register] " + r.RemoteAddr + ": Successfully created user")
|
||||
}
|
||||
@@ -69,6 +74,7 @@ func APILogin(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
|
||||
log.Println("POST [api/login] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", "", "auth.login.failed", "auth", "", "Invalid request", http.StatusBadRequest)
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -76,12 +82,14 @@ func APILogin(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := storage.GetUserByUsername(creds.Username)
|
||||
if err != nil {
|
||||
log.Println("POST [api/login] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", strings.ToLower(strings.TrimSpace(creds.Username)), "auth.login.failed", "auth", "", "Invalid credentials", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if !auth.CheckPasswordHash(creds.Password, user.Password) {
|
||||
log.Println("POST [api/login] " + r.RemoteAddr + ": Invalid credentials")
|
||||
RecordActivity(r, user.ID, user.Username, "auth.login.failed", "auth", "", "Invalid credentials", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -105,11 +113,13 @@ func APILogin(w http.ResponseWriter, r *http.Request) {
|
||||
"requires_2fa": true,
|
||||
"two_factor_token": twoFactorToken,
|
||||
})
|
||||
RecordActivity(r, user.ID, user.Username, "auth.login.password_accepted_2fa_required", "auth", "", "Password accepted; 2FA required", http.StatusOK)
|
||||
log.Println("POST [api/login] " + r.RemoteAddr + ": Password accepted, 2FA required")
|
||||
return
|
||||
}
|
||||
|
||||
issueLoginSession(w, r, user)
|
||||
RecordActivity(r, user.ID, user.Username, "auth.login.succeeded", "auth", "", "Password login succeeded", http.StatusOK)
|
||||
log.Println("POST [api/login] " + r.RemoteAddr + ": Successfully logged in")
|
||||
}
|
||||
|
||||
@@ -120,6 +130,7 @@ func APILoginTwoFactor(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
log.Println("POST [api/login/2fa] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", "", "auth.2fa_login.failed", "auth", "", "Invalid request", http.StatusBadRequest)
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -128,6 +139,7 @@ func APILoginTwoFactor(w http.ResponseWriter, r *http.Request) {
|
||||
claims, err := auth.ValidatePurposeJWT(req.TwoFactorToken, auth.PurposeTwoFactorLogin, secret)
|
||||
if err != nil {
|
||||
log.Println("POST [api/login/2fa] " + r.RemoteAddr + ": " + err.Error())
|
||||
RecordActivity(r, "", "", "auth.2fa_login.failed", "auth", "", "Invalid or expired 2FA challenge", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid or expired 2FA challenge", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -155,15 +167,18 @@ func APILoginTwoFactor(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if !validTOTP && !usedRecoveryCode {
|
||||
log.Println("POST [api/login/2fa] " + r.RemoteAddr + ": Invalid 2FA or recovery code")
|
||||
RecordActivity(r, user.ID, user.Username, "auth.2fa_login.failed", "auth", "", "Invalid 2FA or recovery code", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid 2FA or recovery code", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
issueLoginSession(w, r, user)
|
||||
if usedRecoveryCode {
|
||||
RecordActivity(r, user.ID, user.Username, "auth.recovery_code_login.succeeded", "auth", "", "Recovery-code login succeeded", http.StatusOK)
|
||||
log.Println("POST [api/login/2fa] " + r.RemoteAddr + ": Successfully logged in with recovery code")
|
||||
return
|
||||
}
|
||||
RecordActivity(r, user.ID, user.Username, "auth.2fa_login.succeeded", "auth", "", "2FA login succeeded", http.StatusOK)
|
||||
log.Println("POST [api/login/2fa] " + r.RemoteAddr + ": Successfully logged in with 2FA")
|
||||
}
|
||||
|
||||
@@ -584,6 +599,7 @@ func RefreshToken(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if req.RefreshToken == "" {
|
||||
log.Println("POST [api/refresh] " + r.RemoteAddr + ": Missing refresh token")
|
||||
RecordActivity(r, "", "", "auth.refresh.failed", "auth", "", "Missing refresh token", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid refresh token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -593,6 +609,7 @@ func RefreshToken(w http.ResponseWriter, r *http.Request) {
|
||||
tokenRow, err := storage.GetRefreshToken(hashed)
|
||||
if err != nil || tokenRow.Revoked || tokenRow.ExpiresAt < time.Now().Unix() {
|
||||
log.Println("POST [api/refresh] " + r.RemoteAddr + ": Invalid refresh token")
|
||||
RecordActivity(r, tokenRow.UserID, "", "auth.refresh.failed", "auth", "", "Invalid refresh token", http.StatusUnauthorized)
|
||||
http.Error(w, "Invalid refresh token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -609,6 +626,7 @@ func RefreshToken(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
issueLoginSession(w, r, user)
|
||||
RecordActivity(r, user.ID, user.Username, "auth.refresh.succeeded", "auth", "", "Refresh token rotated", http.StatusOK)
|
||||
log.Println("POST [api/refresh] " + r.RemoteAddr + ": Successfully refreshed token")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user