website/pkg/controller/account/profile.go
Noah 6c91c67c97 More Private User Avatars
* Users who set their Profile Picture to "friends only" or "private" can have
  their avatar be private all over the website to users who are not their
  friends or not granted access.
* Users who are not your friends see a yellow placeholder avatar, and users
  not granted access to a private Profile Pic sees a purple avatar.
* Admin users see these same placeholder avatars most places too (on search,
  forums, comments, etc.) if the user did not friend or grant the admin. But
  admins ALWAYS see it on their Profile Page directly, for ability to moderate.
* Fix marking Notifications as read: clicking the link in an unread notification
  now will wait on the ajax request to finish before allowing the redirect.
* Update the FAQ
2022-09-08 21:42:20 -07:00

115 lines
3.3 KiB
Go

package account
import (
"net/http"
"net/url"
"regexp"
"code.nonshy.com/nonshy/website/pkg/models"
"code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/templates"
)
var ProfileRegexp = regexp.MustCompile(`^/u/([^@]+?)$`)
// User profile page (/u/username)
func Profile() http.HandlerFunc {
tmpl := templates.Must("account/profile.html")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Parse the username out of the URL parameters.
var username string
m := ProfileRegexp.FindStringSubmatch(r.URL.Path)
if m != nil {
username = m[1]
}
// Find this user.
user, err := models.FindUser(username)
if err != nil {
templates.NotFoundPage(w, r)
return
}
// Forcing an external view? (preview of logged-out profile view for visibility=external accounts)
if r.FormValue("view") == "external" {
vars := map[string]interface{}{
"User": user,
"IsPrivate": true,
"IsExternalView": true,
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
return
}
// Get the current user (if logged in). If not, check for external view.
currentUser, err := session.CurrentUser(r)
if err != nil {
// The viewer is not logged in, bail now with the basic profile page. If this
// user doesn't allow external viewers, redirect to login page.
if user.Visibility != models.UserVisibilityExternal {
session.FlashError(w, r, "You must be signed in to view this page.")
templates.Redirect(w, "/login?next="+url.QueryEscape(r.URL.String()))
return
}
vars := map[string]interface{}{
"User": user,
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
return
}
// Inject relationship booleans for profile picture display.
models.SetUserRelationships(currentUser, []*models.User{user})
// Admin user can always see the profile pic - but only on this page. Other avatar displays
// will show the yellow or pink shy.png if the admin is not friends or not granted.
if currentUser.IsAdmin {
user.UserRelationship.IsFriend = true
user.UserRelationship.IsPrivateGranted = true
}
var isSelf = currentUser.ID == user.ID
// Banned or disabled? Only admin can view then.
if user.Status != models.UserStatusActive && !currentUser.IsAdmin {
templates.NotFoundPage(w, r)
return
}
// Is either one blocking?
if models.IsBlocking(currentUser.ID, user.ID) && !currentUser.IsAdmin {
templates.NotFoundPage(w, r)
return
}
// Are they friends? And/or is this user private?
var (
isFriend = models.FriendStatus(currentUser.ID, user.ID)
isPrivate = !currentUser.IsAdmin && !isSelf && user.Visibility == models.UserVisibilityPrivate && isFriend != "approved"
)
// Get Likes for this profile.
likeMap := models.MapLikes(currentUser, "users", []uint64{user.ID})
vars := map[string]interface{}{
"User": user,
"LikeMap": likeMap,
"IsFriend": isFriend,
"IsPrivate": isPrivate,
"PhotoCount": models.CountPhotos(user.ID),
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
}