refactor(postgres): fixed any IDE errors
Signed-off-by: soxx <soxx@fenpa.ws>
This commit is contained in:
parent
55296d9a95
commit
b28891f383
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
|
"git.dragse.it/anthrove/otter-space-sdk/pkg/models"
|
||||||
"git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -111,9 +110,9 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) {
|
func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
|
||||||
var userSources []models.UserSource
|
var userSources []models.UserSource
|
||||||
userSourceMap := make(map[string]graphModels.AnthroveUserRelationship)
|
userSourceMap := make(map[string]models.UserSource)
|
||||||
|
|
||||||
err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error
|
err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -133,10 +132,10 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{
|
userSourceMap[source.DisplayName] = models.UserSource{
|
||||||
UserID: userSource.AccountID,
|
UserID: userSource.AccountID,
|
||||||
Username: userSource.AccountUsername,
|
AccountUsername: userSource.AccountUsername,
|
||||||
Source: graphModels.AnthroveSource{
|
Source: models.Source{
|
||||||
DisplayName: source.DisplayName,
|
DisplayName: source.DisplayName,
|
||||||
Domain: source.Domain,
|
Domain: source.Domain,
|
||||||
Icon: source.Icon,
|
Icon: source.Icon,
|
||||||
@ -151,13 +150,13 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A
|
|||||||
return userSourceMap, nil
|
return userSourceMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) {
|
func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) {
|
||||||
if anthroveUserID == "" || sourceDisplayName == "" {
|
if anthroveUserID == "" || sourceDisplayName == "" {
|
||||||
return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty")
|
return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
var userSources []models.UserSource
|
var userSources []models.UserSource
|
||||||
userSourceMap := make(map[string]graphModels.AnthroveUserRelationship)
|
userSourceMap := make(map[string]models.UserSource)
|
||||||
|
|
||||||
err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error
|
err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,10 +177,10 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{
|
userSourceMap[source.DisplayName] = models.UserSource{
|
||||||
UserID: userSource.AccountID,
|
UserID: userSource.AccountID,
|
||||||
Username: userSource.AccountUsername,
|
AccountUsername: userSource.AccountUsername,
|
||||||
Source: graphModels.AnthroveSource{
|
Source: models.Source{
|
||||||
DisplayName: source.DisplayName,
|
DisplayName: source.DisplayName,
|
||||||
Domain: source.Domain,
|
Domain: source.Domain,
|
||||||
Icon: source.Icon,
|
Icon: source.Icon,
|
||||||
@ -197,62 +196,6 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID
|
|||||||
return userSourceMap, nil
|
return userSourceMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) {
|
|
||||||
|
|
||||||
if anthroveUserID == "" {
|
|
||||||
return nil, fmt.Errorf("anthroveUserID cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
var user models.User
|
|
||||||
var userSources []models.UserSource
|
|
||||||
anthroveUser := &graphModels.AnthroveUser{
|
|
||||||
UserID: anthroveUserID,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := db.WithContext(ctx).First(&user, "id = ?", string(anthroveUserID)).Error
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"anthrove_user_id": anthroveUserID,
|
|
||||||
}).Error("database: failed to get user")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"anthrove_user_id": anthroveUserID,
|
|
||||||
}).Error("database: failed to get user sources")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, userSource := range userSources {
|
|
||||||
var source models.Source
|
|
||||||
err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"source_id": userSource.SourceID,
|
|
||||||
}).Error("database: failed to get source")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
anthroveUser.Relationship = append(anthroveUser.Relationship, graphModels.AnthroveUserRelationship{
|
|
||||||
UserID: userSource.AccountID,
|
|
||||||
Username: userSource.AccountUsername,
|
|
||||||
Source: graphModels.AnthroveSource{
|
|
||||||
DisplayName: source.DisplayName,
|
|
||||||
Domain: source.Domain,
|
|
||||||
Icon: source.Icon,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"anthrove_user_id": anthroveUserID,
|
|
||||||
}).Trace("database: got anthrove user")
|
|
||||||
|
|
||||||
return anthroveUser, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) {
|
func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) {
|
||||||
var users []models.User
|
var users []models.User
|
||||||
var userIDs []models.AnthroveUserID
|
var userIDs []models.AnthroveUserID
|
||||||
@ -274,9 +217,9 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU
|
|||||||
return userIDs, nil
|
return userIDs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) {
|
func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) {
|
||||||
var userFavorites []models.UserFavorite
|
var userFavorites []models.UserFavorite
|
||||||
var favoritePosts []graphModels.FavoritePost
|
var favoritePosts []models.Post
|
||||||
|
|
||||||
err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error
|
err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -298,12 +241,11 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
favoritePosts = append(favoritePosts, graphModels.FavoritePost{
|
favoritePosts = append(favoritePosts,
|
||||||
AnthrovePost: graphModels.AnthrovePost{
|
models.Post{
|
||||||
PostID: models.AnthrovePostID(post.ID),
|
BaseModel: models.BaseModel{ID: post.ID},
|
||||||
Rating: post.Rating,
|
Rating: post.Rating,
|
||||||
},
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -311,10 +253,10 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov
|
|||||||
"anthrove_user_fav_count": len(favoritePosts),
|
"anthrove_user_fav_count": len(favoritePosts),
|
||||||
}).Trace("database: got all anthrove user favorites")
|
}).Trace("database: got all anthrove user favorites")
|
||||||
|
|
||||||
return &graphModels.FavoriteList{Posts: favoritePosts}, nil
|
return &models.FavoriteList{Posts: favoritePosts}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) {
|
func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) {
|
||||||
var userFavorites []models.UserFavorite
|
var userFavorites []models.UserFavorite
|
||||||
err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error
|
err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -346,13 +288,13 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagsWithFrequency []graphModels.TagsWithFrequency
|
var tagsWithFrequency []models.TagsWithFrequency
|
||||||
for data, frequency := range tagFrequency {
|
for data, frequency := range tagFrequency {
|
||||||
tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{
|
tagsWithFrequency = append(tagsWithFrequency, models.TagsWithFrequency{
|
||||||
Frequency: int64(frequency),
|
Frequency: int64(frequency),
|
||||||
Tags: graphModels.AnthroveTag{
|
Tags: models.Tag{
|
||||||
Name: data.name,
|
Name: data.name,
|
||||||
Type: data.typeName,
|
Type: models.TagType(data.typeName),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -795,13 +795,13 @@ func TestGetUserSourceLink(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := GetUserSourceLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID)
|
got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("GetUserSourceLink() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("GetUserSourceLink() got = %v, want %v", got, tt.want)
|
t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -6,45 +6,63 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type OtterSpace interface {
|
type OtterSpace interface {
|
||||||
|
// Connect establishes a connection to the database.
|
||||||
Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error
|
Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error
|
||||||
|
|
||||||
|
// AddUserWithRelationToSource adds a user with a relation to a source.
|
||||||
AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error
|
AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error
|
||||||
|
|
||||||
|
// AddSource adds a new source to the database.
|
||||||
AddSource(ctx context.Context, anthroveSource *models.Source) error
|
AddSource(ctx context.Context, anthroveSource *models.Source) error
|
||||||
|
|
||||||
|
// AddPost adds a new post to the database.
|
||||||
AddPost(ctx context.Context, anthrovePost *models.Post) error
|
AddPost(ctx context.Context, anthrovePost *models.Post) error
|
||||||
|
|
||||||
|
// AddTagWithRelationToPost adds a tag with a relation to a post.
|
||||||
AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error
|
AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error
|
||||||
|
|
||||||
|
// LinkPostWithSource links a post with a source.
|
||||||
LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error
|
LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error
|
||||||
|
|
||||||
|
// LinkUserWithPost links a user with a post.
|
||||||
LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error
|
LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error
|
||||||
|
|
||||||
|
// CheckUserPostLink checks if a user-post link exists.
|
||||||
CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error)
|
CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error)
|
||||||
|
|
||||||
|
// GetPostByAnthroveID retrieves a post by its Anthrove ID.
|
||||||
GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error)
|
GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error)
|
||||||
|
|
||||||
|
// GetPostBySourceURL retrieves a post by its source URL.
|
||||||
GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error)
|
GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error)
|
||||||
|
|
||||||
|
// GetPostBySourceID retrieves a post by its source ID.
|
||||||
GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error)
|
GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error)
|
||||||
|
|
||||||
|
// GetUserFavoriteCount retrieves the count of a user's favorites.
|
||||||
GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error)
|
GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error)
|
||||||
|
|
||||||
|
// GetUserSourceLinks retrieves the source links of a user.
|
||||||
GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error)
|
GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error)
|
||||||
|
|
||||||
|
// GetSpecifiedUserSourceLink retrieves a specified source link of a user.
|
||||||
GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error)
|
GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error)
|
||||||
|
|
||||||
GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error)
|
// GetAllAnthroveUserIDs retrieves all Anthrove user IDs.
|
||||||
|
|
||||||
GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error)
|
GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error)
|
||||||
|
|
||||||
|
// GetUserFavoritePostsWithPagination retrieves a user's favorite posts with pagination.
|
||||||
GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error)
|
GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error)
|
||||||
|
|
||||||
|
// GetUserTagsTroughFavedPosts retrieves a user's tags through their favorited posts.
|
||||||
GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error)
|
GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error)
|
||||||
|
|
||||||
|
// GetAllTags retrieves all tags.
|
||||||
GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error)
|
GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error)
|
||||||
|
|
||||||
|
// GetAllSources retrieves all sources.
|
||||||
GetAllSources(ctx context.Context) ([]models.Source, error)
|
GetAllSources(ctx context.Context) ([]models.Source, error)
|
||||||
|
|
||||||
|
// GetSourceByURL retrieves a source by its URL.
|
||||||
GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error)
|
GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error)
|
||||||
}
|
}
|
||||||
|
@ -109,17 +109,13 @@ func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthrov
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
|
func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) {
|
||||||
return postgres.GetUserSourceLink(ctx, p.db, anthroveUserID)
|
return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) {
|
func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) {
|
||||||
return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName)
|
return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) {
|
|
||||||
return postgres.GetAnthroveUser(ctx, p.db, anthroveUserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) {
|
func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) {
|
||||||
return postgres.GetAllAnthroveUserIDs(ctx, p.db)
|
return postgres.GetAllAnthroveUserIDs(ctx, p.db)
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,5 @@ func (UserFavorite) TableName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FavoriteList struct {
|
type FavoriteList struct {
|
||||||
Posts []UserFavorite `json:"posts,omitempty"`
|
Posts []Post `json:"posts,omitempty"`
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user