Encrypted messaging app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.8 KiB

package Auth
import (
"database/sql/driver"
"encoding/json"
"net/http"
"time"
"git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
"git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
)
type credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
type loginResponse struct {
Status string `json:"status"`
Message string `json:"message"`
AsymmetricPublicKey string `json:"asymmetric_public_key"`
AsymmetricPrivateKey string `json:"asymmetric_private_key"`
UserID string `json:"user_id"`
Username string `json:"username"`
MessageExpiryDefault string `json:"message_expiry_default"`
}
func makeLoginResponse(w http.ResponseWriter, code int, message, pubKey, privKey string, user Models.User) {
var (
status = "error"
messageExpiryRaw driver.Value
messageExpiry string
returnJSON []byte
err error
)
if code >= 200 && code <= 300 {
status = "success"
}
messageExpiryRaw, _ = user.MessageExpiryDefault.Value()
messageExpiry, _ = messageExpiryRaw.(string)
returnJSON, err = json.MarshalIndent(loginResponse{
Status: status,
Message: message,
AsymmetricPublicKey: pubKey,
AsymmetricPrivateKey: privKey,
UserID: user.ID.String(),
Username: user.Username,
MessageExpiryDefault: messageExpiry,
}, "", " ")
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
return
}
// Return updated json
w.WriteHeader(code)
w.Write(returnJSON)
}
// Login logs the user into the system
func Login(w http.ResponseWriter, r *http.Request) {
var (
creds credentials
userData Models.User
session Models.Session
expiresAt time.Time
err error
)
err = json.NewDecoder(r.Body).Decode(&creds)
if err != nil {
makeLoginResponse(w, http.StatusInternalServerError, "An error occurred", "", "", userData)
return
}
userData, err = Database.GetUserByUsername(creds.Username)
if err != nil {
makeLoginResponse(w, http.StatusUnauthorized, "An error occurred", "", "", userData)
return
}
if !CheckPasswordHash(creds.Password, userData.Password) {
makeLoginResponse(w, http.StatusUnauthorized, "An error occurred", "", "", userData)
return
}
// TODO: Revisit before production
expiresAt = time.Now().Add(12 * time.Hour)
session = Models.Session{
UserID: userData.ID,
Expiry: expiresAt,
}
err = Database.CreateSession(&session)
if err != nil {
makeLoginResponse(w, http.StatusUnauthorized, "An error occurred", "", "", userData)
return
}
http.SetCookie(w, &http.Cookie{
Name: "session_token",
Value: session.ID.String(),
Expires: expiresAt,
})
makeLoginResponse(
w,
http.StatusOK,
"Successfully logged in",
userData.AsymmetricPublicKey,
userData.AsymmetricPrivateKey,
userData,
)
}