Skip to content

Commit

Permalink
1266 private vods are still publicly listed (#1340)
Browse files Browse the repository at this point in the history
* Don't show private live stream to non course-admins; show live stream of hidden courses to course admins

* Don't show private VoDs in the playlist to non course admins

* Don't show private VoDs on the course page to non course admins

* On the home page, don't show private VoDs as "LastRecording" / "most recent VoDs" to non course admins

* Change usage of Course.ToDTO, with a mocked admin as the parameter

* No authorization in liveStreams(), as is expected in the tests. This does not affect the result, private live streams are not listed for students.
  • Loading branch information
YiranDuan721 authored and SebiWrn committed May 7, 2024
1 parent a80cdd3 commit a49ade4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 28 deletions.
32 changes: 24 additions & 8 deletions api/courses.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func (r coursesRoutes) getLive(c *gin.Context) {

livestreams := make([]CourseStream, 0)

user := tumLiveContext.User
for _, stream := range streams {
courseForLiveStream, _ := r.GetCourseById(context.Background(), stream.CourseID)

Expand All @@ -153,8 +154,12 @@ func (r coursesRoutes) getLive(c *gin.Context) {
continue
}
}
// Only show hidden streams to admins
if courseForLiveStream.Visibility == "hidden" && (tumLiveContext.User == nil || tumLiveContext.User.Role != model.AdminType) {
// Only show hidden streams to course admins
if courseForLiveStream.Visibility == "hidden" && (tumLiveContext.User == nil || !tumLiveContext.User.IsAdminOfCourse(courseForLiveStream)) {
continue
}
// Only show private streams to course admins
if stream.Private && (tumLiveContext.User == nil || !tumLiveContext.User.IsAdminOfCourse(courseForLiveStream)) {
continue
}
var lectureHall *model.LectureHall
Expand All @@ -175,7 +180,7 @@ func (r coursesRoutes) getLive(c *gin.Context) {
}

livestreams = append(livestreams, CourseStream{
Course: courseForLiveStream.ToDTO(),
Course: courseForLiveStream.ToDTO(user),
Stream: stream.ToDTO(),
LectureHall: lectureHall.ToDTO(),
Viewers: viewers,
Expand Down Expand Up @@ -213,9 +218,10 @@ func (r coursesRoutes) getPublic(c *gin.Context) {
courses = commons.Unique(public, func(c model.Course) uint { return c.ID })
}

user := tumLiveContext.User
resp := make([]model.CourseDTO, len(courses))
for i, course := range courses {
resp[i] = course.ToDTO()
resp[i] = course.ToDTO(user)
}

c.JSON(http.StatusOK, resp)
Expand Down Expand Up @@ -254,10 +260,12 @@ func (r coursesRoutes) getUsers(c *gin.Context) {

sortCourses(courses)
courses = commons.Unique(courses, func(c model.Course) uint { return c.ID })

user := tumLiveContext.User
resp := make([]model.CourseDTO, 0, len(courses))
for _, course := range courses {
if !course.IsHidden() {
resp = append(resp, course.ToDTO())
resp = append(resp, course.ToDTO(user))
}
}

Expand All @@ -275,10 +283,11 @@ func (r coursesRoutes) getPinned(c *gin.Context) {
}

pinnedCourses = commons.Unique(pinnedCourses, func(c model.Course) uint { return c.ID })
user := tumLiveContext.User
resp := make([]model.CourseDTO, 0, len(pinnedCourses))
for _, course := range pinnedCourses {
if !course.IsHidden() {
resp = append(resp, course.ToDTO())
resp = append(resp, course.ToDTO(user))
}
}

Expand Down Expand Up @@ -355,7 +364,14 @@ func (r coursesRoutes) getCourseBySlug(c *gin.Context) {
c.AbortWithStatus(http.StatusUnauthorized)
}

streams := course.Streams
user := tumLiveContext.User
var streams []model.Stream
for _, stream := range course.Streams {
if !stream.Private || (user != nil && user.IsAdminOfCourse(course)) {
streams = append(streams, stream)
}
}

streamsDTO := make([]model.StreamDTO, len(streams))
for i, s := range streams {
err := tools.SetSignedPlaylists(&s, &model.User{
Expand All @@ -380,7 +396,7 @@ func (r coursesRoutes) getCourseBySlug(c *gin.Context) {
}
}

courseDTO := course.ToDTO()
courseDTO := course.ToDTO(tumLiveContext.User)
courseDTO.Streams = streamsDTO
courseDTO.IsAdmin = isAdmin

Expand Down
22 changes: 11 additions & 11 deletions api/courses_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ func TestCoursesCRUD(t *testing.T) {
ExpectedCode: http.StatusOK,
ExpectedResponse: []CourseStream{
{
Course: fpv.ToDTO(),
Course: fpv.ToDTO(testutils.TUMLiveContextAdmin.User),
Stream: testutils.SelfStream.ToDTO(),
Viewers: 0,
},
{
Course: fpv.ToDTO(),
Course: fpv.ToDTO(testutils.TUMLiveContextAdmin.User),
Stream: testutils.StreamFPVLive.ToDTO(),
LectureHall: testutils.LectureHall.ToDTO(),
Viewers: 0,
Expand Down Expand Up @@ -220,8 +220,8 @@ func TestCoursesCRUD(t *testing.T) {
Middlewares: testutils.GetMiddlewares(tools.ErrorHandler, testutils.TUMLiveContext(testutils.TUMLiveContextStudent)),
ExpectedCode: http.StatusOK,
ExpectedResponse: []model.CourseDTO{
testutils.CourseFPV.ToDTO(),
testutils.CourseGBS.ToDTO(),
testutils.CourseFPV.ToDTO(testutils.TUMLiveContextAdmin.User),
testutils.CourseGBS.ToDTO(testutils.TUMLiveContextAdmin.User),
},
},
"success not logged-in": {
Expand All @@ -242,8 +242,8 @@ func TestCoursesCRUD(t *testing.T) {
Middlewares: testutils.GetMiddlewares(tools.ErrorHandler, testutils.TUMLiveContext(testutils.TUMLiveContextUserNil)),
ExpectedCode: http.StatusOK,
ExpectedResponse: []model.CourseDTO{
testutils.CourseFPV.ToDTO(),
testutils.CourseGBS.ToDTO(),
testutils.CourseFPV.ToDTO(testutils.TUMLiveContextAdmin.User),
testutils.CourseGBS.ToDTO(testutils.TUMLiveContextAdmin.User),
},
},
}.
Expand Down Expand Up @@ -286,7 +286,7 @@ func TestCoursesCRUD(t *testing.T) {
Middlewares: testutils.GetMiddlewares(tools.ErrorHandler, testutils.TUMLiveContext(testutils.TUMLiveContextLecturer)),
ExpectedCode: http.StatusOK,
ExpectedResponse: []model.CourseDTO{
testutils.CourseGBS.ToDTO(),
testutils.CourseGBS.ToDTO(testutils.TUMLiveContextAdmin.User),
},
},
"success admin": {
Expand All @@ -307,8 +307,8 @@ func TestCoursesCRUD(t *testing.T) {
Middlewares: testutils.GetMiddlewares(tools.ErrorHandler, testutils.TUMLiveContext(testutils.TUMLiveContextAdmin)),
ExpectedCode: http.StatusOK,
ExpectedResponse: []model.CourseDTO{
testutils.CourseFPV.ToDTO(),
testutils.CourseGBS.ToDTO(),
testutils.CourseFPV.ToDTO(testutils.TUMLiveContextAdmin.User),
testutils.CourseGBS.ToDTO(testutils.TUMLiveContextAdmin.User),
},
},
}.
Expand All @@ -331,7 +331,7 @@ func TestCoursesCRUD(t *testing.T) {
Router: CourseRouterWrapper,
Middlewares: testutils.GetMiddlewares(tools.ErrorHandler, testutils.TUMLiveContext(testutils.TUMLiveContextStudent)),
ExpectedCode: http.StatusOK,
ExpectedResponse: []model.CourseDTO{testutils.CourseFPV.ToDTO()},
ExpectedResponse: []model.CourseDTO{testutils.CourseFPV.ToDTO(testutils.TUMLiveContextAdmin.User)},
},
}.
Method(http.MethodGet).
Expand All @@ -342,7 +342,7 @@ func TestCoursesCRUD(t *testing.T) {
t.Run("GET/api/courses/:slug/", func(t *testing.T) {
url := fmt.Sprintf("/api/courses/%s/", testutils.CourseTensNet.Slug)

response := testutils.CourseTensNet.ToDTO()
response := testutils.CourseTensNet.ToDTO(testutils.TUMLiveContextAdmin.User)
response.Streams = []model.StreamDTO{
testutils.StreamTensNetLive.ToDTO(),
}
Expand Down
12 changes: 12 additions & 0 deletions api/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ func (r streamRoutes) getStream(c *gin.Context) {

stream := *tumLiveContext.Stream
course := *tumLiveContext.Course
user := tumLiveContext.User
if stream.Private && (user == nil || !user.IsAdminOfCourse(course)) {
return
}

c.JSON(http.StatusOK, gin.H{
"course": course.Name,
Expand Down Expand Up @@ -370,10 +374,15 @@ func (r streamRoutes) getStreamPlaylist(c *gin.Context) {
}

tumLiveContext := c.MustGet("TUMLiveContext").(tools.TUMLiveContext)
user := tumLiveContext.User
course, _ := r.GetCourseById(context.Background(), tumLiveContext.Course.ID)

// Create mapping of stream id to progress for all progresses of user
var streamIDs []uint
for _, stream := range tumLiveContext.Course.Streams {
if stream.Private && (user == nil || !user.IsAdminOfCourse(course)) {
continue
}
streamIDs = append(streamIDs, stream.ID)
}
streamProgresses := make(map[uint]model.StreamProgress)
Expand All @@ -388,6 +397,9 @@ func (r streamRoutes) getStreamPlaylist(c *gin.Context) {

var result []StreamPlaylistEntry
for _, stream := range tumLiveContext.Course.Streams {
if stream.Private && (user == nil || !user.IsAdminOfCourse(course)) {
continue
}
result = append(result, StreamPlaylistEntry{
StreamID: stream.ID,
CourseSlug: tumLiveContext.Course.Slug,
Expand Down
24 changes: 15 additions & 9 deletions model/course.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type CourseDTO struct {
IsAdmin bool // Set in API handler
}

func (c *Course) ToDTO() CourseDTO {
func (c *Course) ToDTO(u *User) CourseDTO {
return CourseDTO{
ID: c.ID,
Name: c.Name,
Expand All @@ -65,8 +65,8 @@ func (c *Course) ToDTO() CourseDTO {
TeachingTerm: c.TeachingTerm,
Year: c.Year,
DownloadsEnabled: c.DownloadsEnabled,
NextLecture: c.GetNextLecture().ToDTO(),
LastRecording: c.GetLastRecording().ToDTO(),
NextLecture: c.GetNextLecture(u).ToDTO(),
LastRecording: c.GetLastRecording(u).ToDTO(),
IsAdmin: false,
}
}
Expand Down Expand Up @@ -219,15 +219,18 @@ func (c Course) NumUsers() int {
}

// NextLectureHasReachedTimeSlot returns whether the courses next lecture arrived at its timeslot
func (c Course) NextLectureHasReachedTimeSlot() bool {
return c.GetNextLecture().TimeSlotReached()
func (c Course) NextLectureHasReachedTimeSlot(u *User) bool {
return c.GetNextLecture(u).TimeSlotReached()
}

// GetNextLecture returns the next lecture of the course
func (c Course) GetNextLecture() Stream {
func (c Course) GetNextLecture(u *User) Stream {
var earliestLecture Stream
earliestLectureDate := time.Now().Add(time.Hour * 24 * 365 * 10) // 10 years from now.
for _, s := range c.Streams {
if s.Private && (u == nil || !u.IsAdminOfCourse(c)) {
continue
}
if s.Start.Before(earliestLectureDate) && s.End.After(time.Now()) {
earliestLectureDate = s.Start
earliestLecture = s
Expand All @@ -238,10 +241,13 @@ func (c Course) GetNextLecture() Stream {

// GetLastRecording returns the most recent lecture of the course
// Assumes an ascending order of c.Streams
func (c Course) GetLastRecording() Stream {
func (c Course) GetLastRecording(u *User) Stream {
var lastLecture Stream
now := time.Now()
for _, s := range c.Streams {
if s.Private && (u == nil || !u.IsAdminOfCourse(c)) {
continue
}
if s.Start.After(now) {
return lastLecture
}
Expand Down Expand Up @@ -276,8 +282,8 @@ func (c Course) GetNextLectureDate() time.Time {
}

// IsNextLectureSelfStream checks whether the next lecture is a self stream
func (c Course) IsNextLectureSelfStream() bool {
return c.GetNextLecture().IsSelfStream()
func (c Course) IsNextLectureSelfStream(u *User) bool {
return c.GetNextLecture(u).IsSelfStream()
}

// GetNextLectureDateFormatted returns a JavaScript friendly formatted date string
Expand Down

0 comments on commit a49ade4

Please sign in to comment.