feat: enforce friend add and curfew policies
This commit is contained in:
+47
-1
@@ -3635,6 +3635,10 @@ func serveIMFriendRequestCreate(wrt http.ResponseWriter, req *http.Request) {
|
||||
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "invalid friend request source", nil)
|
||||
return
|
||||
}
|
||||
if decision := imFriendAddPolicyDecision(principal.TenantID, "", principal.Uid, source); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
privacy, err := store.Profiles.GetPrivacy(principal.TenantID, target)
|
||||
if err != nil {
|
||||
writeIMRelationError(wrt, req, err)
|
||||
@@ -4048,10 +4052,14 @@ func serveIMGroupMembers(wrt http.ResponseWriter, req *http.Request, topic strin
|
||||
return
|
||||
}
|
||||
remarks := groupMemberRemarkMap(principal.TenantID, principal.Uid, members)
|
||||
hideFriendEntrypoint := !imFriendGlobalDisabledDecision(principal.TenantID, "", "group").Allowed
|
||||
items := make([]map[string]any, 0, limit)
|
||||
for _, member := range members {
|
||||
access := groupMemberAccess(member)
|
||||
item := groupBusinessMemberPayload(member, remarks[member.UserID])
|
||||
if hideFriendEntrypoint && member.UserID != principal.Uid {
|
||||
maskIMGroupMemberProfileEntrypoint(item)
|
||||
}
|
||||
if eligibleRole != "" {
|
||||
eligible, reason := groupRoleEligibility(selfAccess, access, eligibleRole)
|
||||
item["eligible"] = eligible
|
||||
@@ -5467,6 +5475,12 @@ func serveIMGroupMemberProfile(wrt http.ResponseWriter, req *http.Request, topic
|
||||
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "malformed request", map[string]any{"field": "user_id"})
|
||||
return
|
||||
}
|
||||
if memberID != principal.Uid {
|
||||
if decision := imFriendGlobalDisabledDecision(principal.TenantID, "", "group"); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
}
|
||||
selfSub, err := store.Subs.Get(principal.TenantID, topic, principal.Uid, false)
|
||||
if err != nil {
|
||||
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil)
|
||||
@@ -5519,6 +5533,10 @@ func serveIMMeQRCodes(wrt http.ResponseWriter, req *http.Request) {
|
||||
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "malformed request", map[string]any{"field": "purpose"})
|
||||
return
|
||||
}
|
||||
if decision := imFriendGlobalDisabledDecision(principal.TenantID, "", "qr"); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
expiresIn := body.ExpiresInSeconds
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = imQRCodeDefaultExpiresInSeconds
|
||||
@@ -5624,6 +5642,10 @@ func serveIMQRCodesResolve(wrt http.ResponseWriter, req *http.Request) {
|
||||
writeIMRelationError(wrt, req, err)
|
||||
return
|
||||
}
|
||||
if decision := imFriendGlobalDisabledDecision(principal.TenantID, "", "qr"); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
canAdd := ctx.Relationship == types.RelationshipNone && imPrivacyAllowsAdd(privacy, "qr")
|
||||
action := imRelationshipAction(ctx.Relationship)
|
||||
if ctx.Relationship == types.RelationshipNone && !canAdd {
|
||||
@@ -5665,8 +5687,14 @@ func serveIMUserSearch(wrt http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
payload := make([]map[string]any, 0, len(items))
|
||||
friendSearchAllowed := imFriendGlobalDisabledDecision(principal.TenantID, "", "search").Allowed
|
||||
for _, item := range items {
|
||||
payload = append(payload, userSearchItemPayload(item))
|
||||
data := userSearchItemPayload(item)
|
||||
if !friendSearchAllowed && item.Relationship == types.RelationshipNone {
|
||||
data["can_add"] = false
|
||||
data["action"] = "none"
|
||||
}
|
||||
payload = append(payload, data)
|
||||
}
|
||||
writeIMSuccess(wrt, req, map[string]any{"items": payload, "next_cursor": nextCursor})
|
||||
}
|
||||
@@ -5738,6 +5766,12 @@ func serveIMUserProfile(wrt http.ResponseWriter, req *http.Request, identifier s
|
||||
writeIMError(wrt, req, http.StatusForbidden, 30005, imReasonPermissionDenied, "profile is private", nil)
|
||||
return
|
||||
}
|
||||
if ctx.Relationship == types.RelationshipNone {
|
||||
if decision := imFriendGlobalDisabledDecision(principal.TenantID, "", "profile"); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
}
|
||||
writeIMSuccess(wrt, req, userProfilePayload(user, ctx))
|
||||
}
|
||||
|
||||
@@ -5795,6 +5829,10 @@ func serveIMUserQRCodes(wrt http.ResponseWriter, req *http.Request, identifier s
|
||||
writeIMError(wrt, req, http.StatusForbidden, 30005, imReasonPermissionDenied, "permission denied", nil)
|
||||
return
|
||||
}
|
||||
if decision := imFriendGlobalDisabledDecision(principal.TenantID, "", "qr"); !decision.Allowed {
|
||||
writeIMPolicyDecision(wrt, req, decision)
|
||||
return
|
||||
}
|
||||
}
|
||||
expiresIn := body.ExpiresInSeconds
|
||||
if expiresIn <= 0 {
|
||||
@@ -6932,6 +6970,14 @@ func groupBusinessMemberPayload(member types.GroupMember, remark string) map[str
|
||||
return data
|
||||
}
|
||||
|
||||
func maskIMGroupMemberProfileEntrypoint(data map[string]any) {
|
||||
for _, key := range []string{"avatar_file_id", "public_account", "signature", "gender", "region"} {
|
||||
delete(data, key)
|
||||
}
|
||||
data["can_add"] = false
|
||||
data["action"] = "none"
|
||||
}
|
||||
|
||||
func copyUserNickname(data map[string]any, public any) {
|
||||
var fields map[string]any
|
||||
if value, ok := public.(map[string]any); ok {
|
||||
|
||||
Reference in New Issue
Block a user