login-{validator,app}: Check if the user is already logged elsewhere

This commit is contained in:
nemunaire 2023-02-21 15:24:04 +01:00
commit c313debfdc
4 changed files with 93 additions and 12 deletions

View file

@ -28,6 +28,7 @@ type loginChecker struct {
type loginUpload struct {
Username string
Password string
Force *bool
}
func (l loginChecker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -108,10 +109,26 @@ func (l loginChecker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if mac == nil {
log.Printf("Unable to find MAC address for given IP (%s)\n", ip)
http.Error(w, "Internal server error. Please retry in a few minutes", http.StatusInternalServerError)
http.Error(w, "Unable to find the MAC address of your host. Please retry in a few minutes", http.StatusInternalServerError)
return
}
// Check if the user is already registered
if exists, user, err := l.findUser(lu.Username); exists && (user == nil || mac.HWAddress.String() != user.MAC) {
log.Printf("Find the user in DB: %v", user)
if lu.Force == nil {
log.Println("Successful login of", lu.Username, "at", r.RemoteAddr)
http.Error(w, "You are already registered on a different machine. If you continue, the other machine will no longer be able to use its dedicated IP.", http.StatusPaymentRequired)
return
} else if !*lu.Force {
log.Println("Successful login of", lu.Username, "at", r.RemoteAddr)
http.Error(w, fmt.Sprintf("Use the following IP: %s", ip), http.StatusOK)
return
}
} else if err != nil {
log.Println("An error occurs when searching the user in current DB:", err.Error())
}
// Register the user remotely
if ip, err := l.registerUser(lu.Username, r.RemoteAddr, *mac); err != nil {
log.Println("Error on remote registration for", lu.Username, ":", err)
@ -131,10 +148,37 @@ type myIP struct {
Id int64 `json:"id"`
Login string `json:"login"`
IP string `json:"ip"`
MAC string `json:"mac"`
}
func (l loginChecker) findUser(username string) (bool, *myIP, error) {
req, err := http.NewRequest("GET", "https://adlin.nemunai.re/api/students/"+username+"/", nil)
if err != nil {
return false, nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, nil, err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusNotFound {
return false, nil, nil
} else if resp.StatusCode != http.StatusOK {
return false, nil, errors.New(resp.Status)
} else {
dec := json.NewDecoder(resp.Body)
var myip myIP
if err := dec.Decode(&myip); err != nil {
return true, nil, err
}
return true, &myip, nil
}
}
func (l loginChecker) registerUser(username, remoteAddr string, ent ARPEntry) (net.IP, error) {
bts, err := json.Marshal(map[string]interface{}{"login": username, "ip": remoteAddr, "mac": fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", ent.HWAddress[0], ent.HWAddress[1], ent.HWAddress[2], ent.HWAddress[3], ent.HWAddress[4], ent.HWAddress[5])})
bts, err := json.Marshal(myIP{Login: username, IP: remoteAddr, MAC: ent.HWAddress.String()})
if err != nil {
return nil, nil
}