-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add stories moderation #120
base: main
Are you sure you want to change the base?
Changes from all commits
5ab8633
eeb2106
f0cc654
a681b96
2844a89
622bc5a
feeb540
43ab0dd
d9ffec9
fbd5342
2efef3f
ef9b931
4718094
0e3491e
e54b1ec
0b49dd9
13f32a4
7689df9
a1f84d0
54d9a21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
-- +migrate Up | ||
|
||
ALTER TABLE stories | ||
ADD COLUMN status INT; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there any constraints we want to add? |
||
|
||
-- +migrate Down | ||
|
||
ALTER TABLE stories | ||
DROP COLUMN status; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
-- +migrate Up | ||
|
||
ALTER TABLE stories | ||
ADD COLUMN status_message TEXT; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there any constraints we want to add? |
||
|
||
-- +migrate Down | ||
|
||
ALTER TABLE stories | ||
DROP COLUMN status_message; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,19 +2,31 @@ package model | |
|
||
import ( | ||
"github.com/source-academy/stories-backend/internal/database" | ||
groupenums "github.com/source-academy/stories-backend/internal/enums/groups" | ||
"gorm.io/gorm" | ||
"gorm.io/gorm/clause" | ||
) | ||
|
||
type StoryStatus int | ||
|
||
const ( | ||
Draft StoryStatus = iota | ||
Pending | ||
Rejected | ||
Published | ||
) | ||
Comment on lines
+12
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This enum should not be part of the |
||
|
||
type Story struct { | ||
gorm.Model | ||
AuthorID uint | ||
Author User | ||
GroupID *uint // null means this is a public story | ||
Group Group | ||
Title string | ||
Content string | ||
PinOrder *int // nil if not pinned | ||
AuthorID uint | ||
Author User | ||
GroupID *uint // null means this is a public story | ||
Group Group | ||
Title string | ||
Content string | ||
PinOrder *int // nil if not pinned | ||
Status StoryStatus | ||
StatusMessage *string | ||
} | ||
|
||
// Passing nil to omit the filtering and get all stories | ||
|
@@ -35,6 +47,71 @@ func GetAllStoriesInGroup(db *gorm.DB, groupID *uint) ([]Story, error) { | |
return stories, nil | ||
} | ||
|
||
func GetAllPublishedStories(db *gorm.DB, groupID *uint) ([]Story, error) { | ||
var stories []Story | ||
err := db. | ||
Where("status = ?", int(Published)). | ||
Where("group_id = ?", groupID). | ||
Preload(clause.Associations). | ||
// TODO: Abstract out the sorting logic | ||
Order("pin_order ASC NULLS LAST, title ASC, content ASC"). | ||
Find(&stories). | ||
Error | ||
if err != nil { | ||
return stories, database.HandleDBError(err, "story") | ||
} | ||
return stories, nil | ||
} | ||
|
||
func GetAllPendingStories(db *gorm.DB, groupID *uint) ([]Story, error) { | ||
var stories []Story | ||
err := db. | ||
Where("status = ?", int(Pending)). | ||
Where("group_id = ?", groupID). | ||
Preload(clause.Associations). | ||
// TODO: Abstract out the sorting logic | ||
Order("pin_order ASC NULLS LAST, title ASC, content ASC"). | ||
Find(&stories). | ||
Error | ||
if err != nil { | ||
return stories, database.HandleDBError(err, "story") | ||
} | ||
return stories, nil | ||
} | ||
|
||
func GetAllStoriesByStatus(db *gorm.DB, groupID *uint, status StoryStatus) ([]Story, error) { | ||
var stories []Story | ||
err := db. | ||
Where("status = ?", int(status)). | ||
Where("group_id = ?", groupID). | ||
Preload(clause.Associations). | ||
// TODO: Abstract out the sorting logic | ||
Order("pin_order ASC NULLS LAST, title ASC, content ASC"). | ||
Find(&stories). | ||
Error | ||
if err != nil { | ||
return stories, database.HandleDBError(err, "story") | ||
} | ||
return stories, nil | ||
} | ||
|
||
func GetAllAuthorStoriesByStatus(db *gorm.DB, groupID *uint, userID *int, status StoryStatus) ([]Story, error) { | ||
var stories []Story | ||
err := db. | ||
Where("status = ?", int(status)). | ||
Where("group_id = ?", groupID). | ||
Where("author_id = ?", userID). | ||
Preload(clause.Associations). | ||
// TODO: Abstract out the sorting logic | ||
Order("pin_order ASC NULLS LAST, title ASC, content ASC"). | ||
Find(&stories). | ||
Error | ||
if err != nil { | ||
return stories, database.HandleDBError(err, "story") | ||
} | ||
return stories, nil | ||
} | ||
Comment on lines
+50
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extensive code duplication. This can be easily combined. |
||
|
||
func GetStoryByID(db *gorm.DB, id int) (Story, error) { | ||
var story Story | ||
err := db. | ||
|
@@ -58,8 +135,21 @@ func (s *Story) create(tx *gorm.DB) *gorm.DB { | |
} | ||
|
||
func CreateStory(db *gorm.DB, story *Story) error { | ||
// Check author's role | ||
role, _ := GetUserRoleByID(db, story.AuthorID) | ||
// Based on the TestCreateStory, "can create without group" seems to be the desired behaviour | ||
// No group means no userGroup, which means no role, so an error shouldn't be thrown | ||
// Set story status based on author's role | ||
if !groupenums.IsRoleGreaterThan(role, groupenums.RoleStandard) { | ||
story.Status = Draft | ||
} else { | ||
story.Status = Published | ||
} | ||
err := db.Transaction(func(tx *gorm.DB) error { | ||
return story.create(tx).Error | ||
if err := tx.Create(story).Error; err != nil { | ||
return err // Return the error directly | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
return database.HandleDBError(err, "story") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filtering should be done via a query parameter, not separate routes.