827 lines
28 KiB
Go
827 lines
28 KiB
Go
|
|
// myReviews provides functions to retrieve a user's moderator reviews
|
|
// This package retrieves our reviews from the database.
|
|
// myBroadcasts keeps a backup of a moderator's reviews that is retained if the database is deleted.
|
|
|
|
package myReviews
|
|
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/contentMetadata"
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/identity"
|
|
import "seekia/internal/moderation/createReviews"
|
|
import "seekia/internal/moderation/readReviews"
|
|
import "seekia/internal/myIdentity"
|
|
import "seekia/internal/network/myBroadcasts"
|
|
import "seekia/internal/profiles/profileStorage"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
|
|
import "slices"
|
|
import "bytes"
|
|
import "sync"
|
|
import "errors"
|
|
|
|
|
|
// This function will create and broadcast a new moderator review
|
|
//Outputs:
|
|
// -bool: My moderator identity exists
|
|
// -error
|
|
func CreateAndBroadcastMyReview(reviewMap map[string]string)(bool, error){
|
|
|
|
exists, myIdentityPublicKey, myIdentityPrivateKey, err := myIdentity.GetMyPublicPrivateIdentityKeys("Moderator")
|
|
if (err != nil) { return false, err }
|
|
if (exists == false){
|
|
return false, nil
|
|
}
|
|
|
|
newReview, err := createReviews.CreateReview(myIdentityPublicKey, myIdentityPrivateKey, reviewMap)
|
|
if (err != nil) { return false, err }
|
|
|
|
err = myBroadcasts.BroadcastMyReview(newReview)
|
|
if (err != nil) { return false, err }
|
|
|
|
ableToRead, _, _, _, _, newReviewType, _, _, _, err := readReviews.ReadReview(false, newReview)
|
|
if (err != nil) { return false, err }
|
|
if (ableToRead == false){
|
|
return false, errors.New("CreateReview is returning an invalid review.")
|
|
}
|
|
|
|
err = DeleteMyReviewsListCache(newReviewType)
|
|
if (err != nil) { return false, err }
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// This function will return what a user's current verdict is for an identity
|
|
//Outputs:
|
|
// -bool: My Moderator Identity exists
|
|
// -bool: I have banned the identity
|
|
// -error
|
|
func GetMyNewestIdentityModerationVerdict(identityHash [16]byte, networkType byte)(bool, bool, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, false, errors.New("GetMyNewestIdentityModerationVerdict called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, false, err }
|
|
if (myIdentityExists == false){
|
|
return false, false, nil
|
|
}
|
|
|
|
isValid, err = identity.VerifyIdentityHash(identityHash, false, "")
|
|
if (err != nil) { return false, false, err }
|
|
if (isValid == false){
|
|
identityHashHex := encoding.EncodeBytesToHexString(identityHash[:])
|
|
return false, false, errors.New("GetMyNewestIdentityModerationVerdict called with invalid identityHash: " + identityHashHex)
|
|
}
|
|
|
|
myReviewsList, err := getMyReviewsList(myIdentityHash, "Identity")
|
|
if (err != nil) { return false, false, err }
|
|
|
|
if (len(myReviewsList) == 0){
|
|
// Moderator has no reviews yet
|
|
return true, false, nil
|
|
}
|
|
|
|
reviewExists, _, _, err := readReviews.GetModeratorNewestIdentityReviewFromReviewsList(myReviewsList, myIdentityHash, identityHash, networkType)
|
|
if (err != nil){ return false, false, err }
|
|
if (reviewExists == true){
|
|
// Review must be a ban review, because Identities can only be banned
|
|
return true, true, nil
|
|
}
|
|
|
|
return true, false, nil
|
|
}
|
|
|
|
|
|
// This function will return what a user's current verdict is for a profile
|
|
// This will optionally check for profile attribute bans which would undo a full profile approval
|
|
// It will not check if we have banned the author identity
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -bool: Profile is disabled
|
|
// -bool: Profile metadata exists (needed to determine verdict)
|
|
// -bool: I have reviewed the profile (review exists and is not None)
|
|
// -string: Verdict ("Ban"/"Approve")
|
|
// -error
|
|
func GetMyNewestProfileModerationVerdict(profileHash [28]byte, integrateAttributeBans bool)(bool, bool, bool, bool, string, error){
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, false, false, false, "", err }
|
|
if (myIdentityExists == false){
|
|
return false, false, false, false, "", nil
|
|
}
|
|
|
|
_, profileIsDisabled, err := readProfiles.ReadProfileHashMetadata(profileHash)
|
|
if (err != nil){
|
|
profileHashHex := encoding.EncodeBytesToHexString(profileHash[:])
|
|
return false, false, false, false, "", errors.New("GetMyNewestProfileModerationVerdict called with invalid profile hash: " + profileHashHex)
|
|
}
|
|
|
|
metadataExists, _, profileNetworkType, _, _, profileIsDisabledB, _, attributeHashesMap, err := contentMetadata.GetProfileMetadata(profileHash)
|
|
if (err != nil) { return false, false, false, false, "", err }
|
|
if (metadataExists == false){
|
|
return true, profileIsDisabled, false, false, "", nil
|
|
}
|
|
if (profileIsDisabled != profileIsDisabledB){
|
|
return false, false, false, false, "", errors.New("GetProfileMetadata returning different profileIsDisabled status than ReadProfileHashMetadata.")
|
|
}
|
|
if (profileIsDisabled == true){
|
|
// Profile is disabled. It cannot be reviewed.
|
|
return true, true, true, false, "", nil
|
|
}
|
|
|
|
myProfileReviewsList, err := getMyReviewsList(myIdentityHash, "Profile")
|
|
if (err != nil) { return false, false, false, false, "", err }
|
|
|
|
fullProfileReviewExists, _, _, fullProfileVerdict, fullProfileVerdictTime, err := readReviews.GetModeratorNewestProfileReviewFromReviewsList(myProfileReviewsList, myIdentityHash, profileHash, profileNetworkType)
|
|
if (err != nil){ return false, false, false, false, "", err }
|
|
|
|
if (integrateAttributeBans == false){
|
|
if (fullProfileReviewExists == true){
|
|
|
|
return true, false, true, true, fullProfileVerdict, nil
|
|
}
|
|
|
|
return true, false, true, false, "", nil
|
|
}
|
|
|
|
if (fullProfileReviewExists == true && fullProfileVerdict == "Ban"){
|
|
// We do not have to check if we have banned any profile attributes, because we have already banned the full profile
|
|
return true, false, true, true, "Ban", nil
|
|
}
|
|
|
|
// Now we see if we have banned any attributes belonging to this profile
|
|
|
|
for _, attributeHash := range attributeHashesMap{
|
|
|
|
myIdentityExists, attributeMetadataExists, reviewExists, myVerdict, myVerdictTime, err := GetMyNewestProfileAttributeModerationVerdict(attributeHash, false)
|
|
if (err != nil) { return false, false, false, false, "", err }
|
|
if (myIdentityExists == false){
|
|
return false, false, false, false, "", errors.New("My identity not found after being found already.")
|
|
}
|
|
if (attributeMetadataExists == false){
|
|
// We don't have knowledge of profiles belonging to this profile in the attributeProfileHashesList entry in the database
|
|
// This should not happen unless those entries were deleted
|
|
// We will interpret this the same as no other profiles existing which contain this attribute
|
|
continue
|
|
}
|
|
if (reviewExists == true && myVerdict == "Ban"){
|
|
|
|
if (fullProfileReviewExists == true && myVerdictTime < fullProfileVerdictTime){
|
|
// We have approved the full profile after we banned this attribute
|
|
continue
|
|
}
|
|
// We have banned a profile attribute, thus, we have banned the profile.
|
|
|
|
return true, false, true, true, "Ban", nil
|
|
}
|
|
}
|
|
|
|
if (fullProfileReviewExists == true){
|
|
// We could not find any attribute bans that undo the full profile approval
|
|
return true, false, true, true, "Approve", nil
|
|
}
|
|
|
|
return true, false, true, false, "", nil
|
|
}
|
|
|
|
|
|
// This function will return a user's newest profile attribute verdict
|
|
// It will optionally check for full profile approvals, which it considers the same as approving all of the profile's attributes
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -bool: Attribute metadata exists (this is needed to determine verdict)
|
|
// -bool: I have reviewed the attribute (review exists and is not None)
|
|
// -string: Verdict ("Ban"/"Approve")
|
|
// -int64: Time of verdict
|
|
// -error
|
|
func GetMyNewestProfileAttributeModerationVerdict(attributeHash [27]byte, integrateFullProfileApprovals bool)(bool, bool, bool, string, int64, error){
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, false, false, "", 0, err }
|
|
if (myIdentityExists == false){
|
|
return false, false, false, "", 0, nil
|
|
}
|
|
|
|
isValid, err := readProfiles.VerifyAttributeHash(attributeHash, false, "", false, false)
|
|
if (err != nil) { return false, false, false, "", 0, err }
|
|
if (isValid == false){
|
|
attributeHashHex := encoding.EncodeBytesToHexString(attributeHash[:])
|
|
return false, false, false, "", 0, errors.New("GetMyNewestProfileAttributeModerationVerdict called with invalid attributeHash: " + attributeHashHex)
|
|
}
|
|
|
|
attributeMetadataExists, _, _, attributeNetworkType, attributeProfileHashesList, err := profileStorage.GetProfileAttributeMetadata(attributeHash)
|
|
if (err != nil) { return false, false, false, "", 0, err }
|
|
if (attributeMetadataExists == false){
|
|
// We cannot determine verdict.
|
|
return true, false, false, "", 0, nil
|
|
}
|
|
|
|
myAttributeReviewsList, err := getMyReviewsList(myIdentityHash, "Attribute")
|
|
if (err != nil) { return false, false, false, "", 0, err }
|
|
|
|
attributeReviewExists, _, _, attributeReviewVerdict, attributeReviewTime, err := readReviews.GetModeratorNewestProfileAttributeReviewFromReviewsList(myAttributeReviewsList, myIdentityHash, attributeHash, attributeNetworkType)
|
|
if (err != nil){ return false, false, false, "", 0, err }
|
|
|
|
if (integrateFullProfileApprovals == false){
|
|
|
|
if (attributeReviewExists == false){
|
|
return true, true, false, "", 0, nil
|
|
}
|
|
|
|
return true, true, true, attributeReviewVerdict, attributeReviewTime, nil
|
|
}
|
|
|
|
if (attributeReviewExists == true && attributeReviewVerdict == "Approve"){
|
|
|
|
// We approved the attribute
|
|
// We don't have to check for full profile approvals, because they would not change this verdict
|
|
|
|
return true, true, true, "Approve", attributeReviewTime, nil
|
|
}
|
|
|
|
// Now we check for full profile approvals
|
|
// A full profile approval is equivalent to an attribute approval for all attributes within the profile
|
|
// attributeProfileHashesList is a list of all profile hashes for profiles which contain the attribute
|
|
|
|
myProfileReviewsList, err := getMyReviewsList(myIdentityHash, "Profile")
|
|
if (err != nil) { return false, false, false, "", 0, err }
|
|
|
|
for _, profileHash := range attributeProfileHashesList{
|
|
|
|
// We are only checking for full profile approvals
|
|
// We don't need to check for profile attribute bans, because we are only concerned with the provided attribute's status
|
|
// A full profile approval approves all attributes.
|
|
// If we ban a full profile, it does not change the status of any of our attribute approvals of the profile
|
|
|
|
fullProfileReviewExists, _, _, fullProfileVerdict, fullProfileVerdictTime, err := readReviews.GetModeratorNewestProfileReviewFromReviewsList(myProfileReviewsList, myIdentityHash, profileHash, attributeNetworkType)
|
|
if (err != nil){ return false, false, false, "", 0, err }
|
|
if (fullProfileReviewExists == true && fullProfileVerdict == "Approve"){
|
|
|
|
if (attributeReviewExists == true && fullProfileVerdictTime < attributeReviewTime){
|
|
// We banned the attribute after approving the full profile
|
|
// The attribute ban is therefore disregarded.
|
|
continue
|
|
}
|
|
// We have approved the full profile after banning the attribute, thus, the attribute is approved
|
|
|
|
return true, true, true, "Approve", fullProfileVerdictTime, nil
|
|
}
|
|
}
|
|
|
|
if (attributeReviewExists == true){
|
|
// We could not find any full profile approvals that undo the attribute ban
|
|
return true, true, true, "Ban", attributeReviewTime, nil
|
|
}
|
|
|
|
return true, true, false, "", 0, nil
|
|
}
|
|
|
|
|
|
// This function will return what a user's current verdict is for a message
|
|
// -bool: My Moderator Identity exists
|
|
// -bool: Message metadata exists (this is needed to determine our verdict)
|
|
// -bool: I have reviewed the message (review exists and is not None)
|
|
// -string: Verdict ("Ban"/"Approve")
|
|
// -error
|
|
func GetMyNewestMessageModerationVerdict(messageHash [26]byte)(bool, bool, bool, string, error){
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, false, false, "", err }
|
|
if (myIdentityExists == false){
|
|
return false, false, false, "", nil
|
|
}
|
|
|
|
messageMetadataExists, _, messageNetworkType, _, _, messageCipherKeyHash, err := contentMetadata.GetMessageMetadata(messageHash)
|
|
if (err != nil){ return false, false, false, "", err }
|
|
if (messageMetadataExists == false){
|
|
// We cannot determine our verdict without message metadata
|
|
return true, false, false, "", nil
|
|
}
|
|
|
|
myReviewsList, err := getMyReviewsList(myIdentityHash, "Message")
|
|
if (err != nil) { return false, false, false, "", err }
|
|
|
|
if (len(myReviewsList) == 0){
|
|
// Moderator has no reviews yet
|
|
return true, true, false, "", nil
|
|
}
|
|
|
|
reviewExists, _, _, reviewVerdict, err := readReviews.GetModeratorNewestMessageReviewFromReviewsList(myReviewsList, myIdentityHash, messageHash, messageNetworkType, messageCipherKeyHash)
|
|
if (err != nil){ return false, false, false, "", err }
|
|
if (reviewExists == false){
|
|
return true, true, false, "", nil
|
|
}
|
|
|
|
return true, true, true, reviewVerdict, nil
|
|
}
|
|
|
|
// This function returns a list of all the identity hashes that the user has banned
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -[][16]byte: List of identity hashes user has banned
|
|
// -error
|
|
func GetMyBannedIdentityHashesList(networkType byte)(bool, [][16]byte, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, errors.New("GetMyBannedIdentityHashesList called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
myIdentityReviewsMap, err := getMyNewestReviewsMap(myIdentityHash, "Identity", networkType)
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
bannedIdentityHashesList := make([][16]byte, 0, len(myIdentityReviewsMap))
|
|
|
|
for reviewedIdentityHashString, _ := range myIdentityReviewsMap{
|
|
|
|
reviewedIdentityHashBytes := []byte(reviewedIdentityHashString)
|
|
|
|
if (len(reviewedIdentityHashBytes) != 16){
|
|
reviewedIdentityHashHex := encoding.EncodeBytesToHexString(reviewedIdentityHashBytes)
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning invalid reviewedIdentityHash: " + reviewedIdentityHashHex)
|
|
}
|
|
|
|
reviewedIdentityHash := [16]byte(reviewedIdentityHashBytes)
|
|
|
|
bannedIdentityHashesList = append(bannedIdentityHashesList, reviewedIdentityHash)
|
|
}
|
|
|
|
return true, bannedIdentityHashesList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -map[[28]byte]string: Map of profile hashes user has reviewed (Profile hash -> "Approve"/"Ban")
|
|
// -error
|
|
func GetMyReviewedProfileHashesMap(profileType string, networkType byte)(bool, map[[28]byte]string, error){
|
|
|
|
if (profileType != "Mate" && profileType != "Host" && profileType != "Moderator"){
|
|
return false, nil, errors.New("GetMyReviewedProfileHashesMap called with invalid profile type: " + profileType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, errors.New("GetMyReviewedProfileHashesMap called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, _, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
allProfileHashesList, err := badgerDatabase.GetAllProfileHashes(profileType)
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
//Map structure: Profile hash -> My Verdict
|
|
myReviewedProfileHashesMap := make(map[[28]byte]string)
|
|
|
|
for _, profileHash := range allProfileHashesList{
|
|
|
|
myIdentityExists, profileIsDisabled, profileMetadataExists, iHaveReviewed, myVerdict, err := GetMyNewestProfileModerationVerdict(profileHash, true)
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, errors.New("My identity not found after being found already.")
|
|
}
|
|
if (profileIsDisabled == true){
|
|
continue
|
|
}
|
|
if (profileMetadataExists == false){
|
|
continue
|
|
}
|
|
|
|
if (iHaveReviewed == true){
|
|
myReviewedProfileHashesMap[profileHash] = myVerdict
|
|
}
|
|
}
|
|
|
|
return true, myReviewedProfileHashesMap, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -map[[27]byte]string: Map Structure: Attribute Hash -> Verdict
|
|
// -Map of profile attribute hashes user has reviewed (approved or banned)
|
|
// -error
|
|
func GetMyReviewedProfileAttributeHashesMap(networkType byte)(bool, map[[27]byte]string, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, errors.New("GetMyReviewedProfileAttributeHashesMap called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, _, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
allProfileAttributeHashesList, err := badgerDatabase.GetAllReviewedProfileAttributeHashes()
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
//Map structure: Attribute hash -> My verdict
|
|
myAttributeVerdictsMap := make(map[[27]byte]string)
|
|
|
|
for _, attributeHash := range allProfileAttributeHashesList{
|
|
|
|
myIdentityExists, attributeMetadataExists, myReviewExists, myVerdict, _, err := GetMyNewestProfileAttributeModerationVerdict(attributeHash, true)
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, errors.New("My moderator identity not found after being found already.")
|
|
}
|
|
if (attributeMetadataExists == false){
|
|
// We cannot determine our verdict for this attribute
|
|
continue
|
|
}
|
|
if (myReviewExists == true){
|
|
myAttributeVerdictsMap[attributeHash] = myVerdict
|
|
}
|
|
}
|
|
|
|
return true, myAttributeVerdictsMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: My Moderator identity exists
|
|
// -[][26]byte: List of message hashes user has reviewed (approved or banned)
|
|
// -error
|
|
func GetMyReviewedMessageHashesList(networkType byte)(bool, [][26]byte, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, errors.New("GetMyReviewedMessageHashesList called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
myMessageReviewsMap, err := getMyNewestReviewsMap(myIdentityHash, "Message", networkType)
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
myReviewedMessageHashesList := make([][26]byte, 0, len(myMessageReviewsMap))
|
|
|
|
for messageHashString, reviewBytes := range myMessageReviewsMap{
|
|
|
|
messageHashBytes := []byte(messageHashString)
|
|
|
|
if (len(messageHashBytes) != 26){
|
|
messageHashHex := encoding.EncodeBytesToHexString(messageHashBytes)
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning reviewsMap with invalid messageHash map key: " + messageHashHex)
|
|
}
|
|
|
|
messageHashArray := [26]byte(messageHashBytes)
|
|
|
|
ableToRead, _, reviewNetworkType, reviewerIdentityHash, _, reviewType, reviewedHash, _, _, err := readReviews.ReadReview(false, reviewBytes)
|
|
if (err != nil) { return false, nil, err }
|
|
if (ableToRead == false){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning invalid review.")
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning review of different networkType.")
|
|
}
|
|
|
|
if (reviewerIdentityHash != myIdentityHash){
|
|
return false, nil, errors.New("getMyNewestReviewsMap list contains review by different reviewer")
|
|
}
|
|
|
|
if (reviewType != "Message"){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returns different reviewType review: " + reviewType)
|
|
}
|
|
|
|
areEqual := bytes.Equal(reviewedHash, messageHashBytes)
|
|
if (areEqual == false){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returns key with different review reviewedHash")
|
|
}
|
|
|
|
myReviewedMessageHashesList = append(myReviewedMessageHashesList, messageHashArray)
|
|
}
|
|
|
|
return true, myReviewedMessageHashesList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: User moderator identity found
|
|
// -[][]byte: List of all reviews created by user, sorted from newest to oldest (Reviews with None verdict not included)
|
|
// -error
|
|
func GetMyNewestReviewsListSorted(reviewType string, networkType byte)(bool, [][]byte, error){
|
|
|
|
if (reviewType != "Identity" && reviewType != "Profile" && reviewType != "Attribute" && reviewType != "Message"){
|
|
return false, nil, errors.New("GetMyNewestReviewsListSorted called with invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, errors.New("GetMyNewestReviewsListSorted called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Moderator")
|
|
if (err != nil) { return false, nil, err }
|
|
if (myIdentityExists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
myNewestReviewsMap, err := getMyNewestReviewsMap(myIdentityHash, reviewType, networkType)
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
type ReviewObject struct{
|
|
ReviewBroadcastTime int64
|
|
ReviewBytes []byte
|
|
}
|
|
|
|
newestReviewObjectsList := make([]ReviewObject, 0, len(myNewestReviewsMap))
|
|
|
|
for reviewedHashString, reviewBytes := range myNewestReviewsMap{
|
|
|
|
reviewedHashBytes := []byte(reviewedHashString)
|
|
|
|
ableToRead, _, reviewNetworkType, reviewAuthorIdentityHash, reviewBroadcastTime, currentReviewType, currentReviewedHash, _, _, err := readReviews.ReadReview(false, reviewBytes)
|
|
if (err != nil) { return false, nil, err }
|
|
if (ableToRead == false){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning invalid review")
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning review for different networkType.")
|
|
}
|
|
if (reviewAuthorIdentityHash != myIdentityHash){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning review by different author.")
|
|
}
|
|
if (currentReviewType != reviewType){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning review of a different reviewType.")
|
|
}
|
|
areEqual := bytes.Equal(reviewedHashBytes, currentReviewedHash)
|
|
if (areEqual == false){
|
|
return false, nil, errors.New("getMyNewestReviewsMap returning map where reviewedHash key does not match reviewBytes's.")
|
|
}
|
|
|
|
reviewObject := ReviewObject{
|
|
ReviewBroadcastTime: reviewBroadcastTime,
|
|
ReviewBytes: reviewBytes,
|
|
}
|
|
|
|
newestReviewObjectsList = append(newestReviewObjectsList, reviewObject)
|
|
}
|
|
|
|
compareReviewsFunction := func(reviewA ReviewObject, reviewB ReviewObject)int{
|
|
|
|
reviewABroadcastTime := reviewA.ReviewBroadcastTime
|
|
reviewBBroadcastTime := reviewB.ReviewBroadcastTime
|
|
|
|
if (reviewABroadcastTime == reviewBBroadcastTime){
|
|
return 0
|
|
}
|
|
|
|
if (reviewABroadcastTime < reviewBBroadcastTime){
|
|
return 1
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
slices.SortFunc(newestReviewObjectsList, compareReviewsFunction)
|
|
|
|
newestReviewsList := make([][]byte, 0, len(newestReviewObjectsList))
|
|
|
|
for _, reviewObject := range newestReviewObjectsList{
|
|
|
|
reviewBytes := reviewObject.ReviewBytes
|
|
|
|
newestReviewsList = append(newestReviewsList, reviewBytes)
|
|
}
|
|
|
|
return true, newestReviewsList, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -map[string]string: Reviewed Hash -> Newest Review Bytes
|
|
// -error
|
|
func getMyNewestReviewsMap(myIdentityHash [16]byte, reviewType string, networkType byte)(map[string][]byte, error){
|
|
|
|
if (reviewType != "Identity" && reviewType != "Profile" && reviewType != "Attribute" && reviewType != "Message"){
|
|
return nil, errors.New("getMyNewestReviewsMap called with invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
reviewsList, err := getMyReviewsList(myIdentityHash, reviewType)
|
|
if (err != nil) { return nil, err }
|
|
|
|
newestReviewsMap, err := readReviews.GetNewestModeratorReviewsMapFromReviewsList(reviewsList, myIdentityHash, networkType, true, reviewType)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return newestReviewsMap, nil
|
|
}
|
|
|
|
|
|
// We read our reviews into memory so we don't have to retrieve them from the database each time
|
|
|
|
var myIdentityReviewsList []readReviews.ReviewWithHash
|
|
var myIdentityReviewsListMutex sync.RWMutex
|
|
|
|
var myProfileReviewsList []readReviews.ReviewWithHash
|
|
var myProfileReviewsListMutex sync.RWMutex
|
|
|
|
var myAttributeReviewsList []readReviews.ReviewWithHash
|
|
var myAttributeReviewsListMutex sync.RWMutex
|
|
|
|
var myMessageReviewsList []readReviews.ReviewWithHash
|
|
var myMessageReviewsListMutex sync.RWMutex
|
|
|
|
// We call this function whenever we add a new review to the database
|
|
func DeleteMyReviewsListCache(reviewType string)error{
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
myIdentityReviewsListMutex.Lock()
|
|
myIdentityReviewsList = nil
|
|
myIdentityReviewsListMutex.Unlock()
|
|
|
|
return nil
|
|
|
|
} else if (reviewType == "Profile"){
|
|
|
|
myProfileReviewsListMutex.Lock()
|
|
myProfileReviewsList = nil
|
|
myProfileReviewsListMutex.Unlock()
|
|
|
|
return nil
|
|
|
|
} else if (reviewType == "Attribute"){
|
|
|
|
myAttributeReviewsListMutex.Lock()
|
|
myAttributeReviewsList = nil
|
|
myAttributeReviewsListMutex.Unlock()
|
|
|
|
return nil
|
|
|
|
} else if (reviewType == "Message"){
|
|
|
|
myMessageReviewsListMutex.Lock()
|
|
myMessageReviewsList = nil
|
|
myMessageReviewsListMutex.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
return errors.New("DeleteMyReviewsListCache called with invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
|
|
// This function returns our reviews for all networkTypes.
|
|
// It does not copy each review object's review bytes, so returned review bytes should never be edited
|
|
func getMyReviewsList(myIdentityHash [16]byte, reviewType string)([]readReviews.ReviewWithHash, error){
|
|
|
|
// We first attempt to return the list stored in memory
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
myIdentityReviewsListMutex.RLock()
|
|
if (myIdentityReviewsList != nil){
|
|
|
|
listCopy := slices.Clone(myIdentityReviewsList)
|
|
myIdentityReviewsListMutex.RUnlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
myIdentityReviewsListMutex.RUnlock()
|
|
|
|
} else if (reviewType == "Profile"){
|
|
|
|
myProfileReviewsListMutex.RLock()
|
|
if (myProfileReviewsList != nil){
|
|
|
|
listCopy := slices.Clone(myProfileReviewsList)
|
|
myProfileReviewsListMutex.RUnlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
myProfileReviewsListMutex.RUnlock()
|
|
|
|
} else if (reviewType == "Attribute"){
|
|
|
|
myAttributeReviewsListMutex.RLock()
|
|
if (myAttributeReviewsList != nil){
|
|
|
|
listCopy := slices.Clone(myAttributeReviewsList)
|
|
myAttributeReviewsListMutex.RUnlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
myAttributeReviewsListMutex.RUnlock()
|
|
|
|
} else if (reviewType == "Message"){
|
|
|
|
myMessageReviewsListMutex.RLock()
|
|
if (myMessageReviewsList != nil){
|
|
|
|
listCopy := slices.Clone(myMessageReviewsList)
|
|
myMessageReviewsListMutex.RUnlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
myMessageReviewsListMutex.RUnlock()
|
|
} else {
|
|
return nil, errors.New("getMyReviewsList called with invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
// The list does not exist in memory
|
|
// We will create a new list
|
|
|
|
exists, myReviewHashesList, err := badgerDatabase.GetReviewerReviewHashesList(myIdentityHash, reviewType)
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
emptyList := make([]readReviews.ReviewWithHash, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
newReviewsList := make([]readReviews.ReviewWithHash, 0)
|
|
|
|
for _, reviewHash := range myReviewHashesList{
|
|
|
|
exists, reviewBytes, err := badgerDatabase.GetReview(reviewHash)
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false) {
|
|
// Reviewer reviews list is outdated, will be updated automatically
|
|
continue
|
|
}
|
|
|
|
reviewObject := readReviews.ReviewWithHash{
|
|
ReviewHash: reviewHash,
|
|
ReviewBytes: reviewBytes,
|
|
}
|
|
|
|
newReviewsList = append(newReviewsList, reviewObject)
|
|
}
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
myIdentityReviewsListMutex.Lock()
|
|
|
|
myIdentityReviewsList = newReviewsList
|
|
|
|
listCopy := slices.Clone(myIdentityReviewsList)
|
|
|
|
myIdentityReviewsListMutex.Unlock()
|
|
|
|
return listCopy, nil
|
|
|
|
} else if (reviewType == "Profile"){
|
|
|
|
myProfileReviewsListMutex.Lock()
|
|
|
|
myProfileReviewsList = newReviewsList
|
|
|
|
listCopy := slices.Clone(myProfileReviewsList)
|
|
|
|
myProfileReviewsListMutex.Unlock()
|
|
|
|
return listCopy, nil
|
|
|
|
} else if (reviewType == "Attribute"){
|
|
|
|
myAttributeReviewsListMutex.Lock()
|
|
|
|
myAttributeReviewsList = newReviewsList
|
|
|
|
listCopy := slices.Clone(myAttributeReviewsList)
|
|
|
|
myAttributeReviewsListMutex.Unlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
// reviewType == "Message"){
|
|
|
|
myMessageReviewsListMutex.Lock()
|
|
|
|
myMessageReviewsList = newReviewsList
|
|
|
|
listCopy := slices.Clone(myMessageReviewsList)
|
|
|
|
myMessageReviewsListMutex.Unlock()
|
|
|
|
return listCopy, nil
|
|
}
|
|
|
|
|
|
|
|
|