diff --git a/api/auth.go b/api/auth.go index 03c9ba2..1e14048 100644 --- a/api/auth.go +++ b/api/auth.go @@ -720,6 +720,67 @@ func routeAuthLogout(w http.ResponseWriter, r *http.Request, p httprouter.Params writeJSON(w, http.StatusOK, statusResponse{"ok"}) } +func routeAuthRequestAccountDelete(w http.ResponseWriter, r *http.Request, p httprouter.Params, c RouteContext) { + if r.FormValue("clientType") == "" || r.FormValue("password") == "" { + writeJSON(w, http.StatusBadRequest, errorResponse{"error", "missing_params"}) + return + } + + clientType := r.FormValue("clientType") + password := r.FormValue("password") + + if c.User.PasswordHash == "" { + errorlog.LogError("user request account deletion", errors.New("user is missing password hash")) + writeJSON(w, http.StatusInternalServerError, errorResponse{"error", "internal_server_error"}) + return + } + + err := bcrypt.CompareHashAndPassword([]byte(c.User.PasswordHash), []byte(password)) + if err == bcrypt.ErrMismatchedHashAndPassword { + // bye + writeJSON(w, http.StatusUnauthorized, errorResponse{"error", "password_incorrect"}) + return + } else if err != nil { + errorlog.LogError("user request account deletion", err) + writeJSON(w, http.StatusInternalServerError, errorResponse{"error", "internal_server_error"}) + return + } + + deviceText := map[string]string{ + "web": "our website", + "ios": "an iOS device", + "android": "an Android device", + }[clientType] + ipAddress := getRequestRemoteAddr(r) + + // if we got here, no error -> password correct + + // send the deletion emails + + err = email.Send("", c.User, "accountDeletionRequest", map[string]interface{}{ + "DeviceText": deviceText, + "IPAddress": ipAddress, + }) + if err != nil { + errorlog.LogError("user request account deletion", err) + writeJSON(w, http.StatusInternalServerError, errorResponse{"error", "internal_server_error"}) + return + } + + adminEmail := "astuder@myhomework.space" + err = email.Send(adminEmail, c.User, "accountDeletionRequest", map[string]interface{}{ + "DeviceText": deviceText, + "IPAddress": ipAddress, + }) + if err != nil { + errorlog.LogError("user request account deletion", err) + writeJSON(w, http.StatusInternalServerError, errorResponse{"error", "internal_server_error"}) + return + } + + writeJSON(w, http.StatusOK, statusResponse{"ok"}) +} + func routeAuthResendVerificationEmail(w http.ResponseWriter, r *http.Request, p httprouter.Params, c RouteContext) { if c.User.EmailVerified { writeJSON(w, http.StatusBadRequest, errorResponse{"error", "already_verified"}) diff --git a/api/main.go b/api/main.go index 00198e4..3ae653d 100644 --- a/api/main.go +++ b/api/main.go @@ -287,6 +287,7 @@ func Init(router *httprouter.Router) { router.POST("/auth/login", route(routeAuthLogin, authLevelNone)) router.GET("/auth/me", route(routeAuthMe, authLevelLoggedIn)) router.GET("/auth/logout", route(routeAuthLogout, authLevelLoggedIn)) + router.POST("/auth/requestAccountDelete", route(routeAuthRequestAccountDelete, authLevelLoggedIn)) router.POST("/auth/resetPassword", route(routeAuthResetPassword, authLevelNone)) router.POST("/auth/resendVerificationEmail", route(routeAuthResendVerificationEmail, authLevelNone)) router.GET("/auth/session", route(routeAuthSession, authLevelNone)) diff --git a/templates/accountDeletionRequest/subject.txt b/templates/accountDeletionRequest/subject.txt new file mode 100644 index 0000000..97f14aa --- /dev/null +++ b/templates/accountDeletionRequest/subject.txt @@ -0,0 +1 @@ +Your account has been scheduled for deletion \ No newline at end of file diff --git a/templates/accountDeletionRequest/template.html b/templates/accountDeletionRequest/template.html new file mode 100644 index 0000000..fef1d87 --- /dev/null +++ b/templates/accountDeletionRequest/template.html @@ -0,0 +1,15 @@ +{{template "header"}} +Hi {{.User.Name | fname}},
+
+You requested deletion of your MyHomeworkSpace account with email {{.User.Email}}. It will be deleted within 48 hours. This includes all homework, classes, and calendar events on your account.
+
+If you did not make this request, email hello@myhomework.space immediately to cancel it.
+
+Note that some of your data might remain on our systems even after your account is deleted - for example, your account might still be present in our automated database backups.
+
+The request was made on {{.Data.DeviceText}} from IP address {{.Data.IPAddress}}.
+
+We thank you for using our service. If you have any feedback to share, please email hello@myhomework.space.
+
+MyHomeworkSpace
+{{template "footer"}} \ No newline at end of file diff --git a/templates/accountDeletionRequest/template.txt b/templates/accountDeletionRequest/template.txt new file mode 100644 index 0000000..71b38fc --- /dev/null +++ b/templates/accountDeletionRequest/template.txt @@ -0,0 +1,13 @@ +Hi {{.User.Name | fname}}, + +You requested deletion of your MyHomeworkSpace account with email {{.User.Email}}. It will be deleted within 48 hours. This includes all homework, classes, and calendar events on your account. + +If you did not make this request, email hello@myhomework.space immediately to cancel it. + +Note that some of your data might remain on our systems even after your account is deleted - for example, your account might still be present in our automated database backups. + +The request was made on {{.Data.DeviceText}} from IP address {{.Data.IPAddress}}. + +We thank you for using our service. If you have any feedback to share, please email hello@myhomework.space. + +MyHomeworkSpace \ No newline at end of file