Skip to content

Commit

Permalink
Further course import improvements (TUM-Dev#717)
Browse files Browse the repository at this point in the history
* add opt out page

* fix some minor issues

* add opt out to mail
  • Loading branch information
joschahenningsen authored Oct 10, 2022
1 parent 7b3de4d commit d94bd67
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 10 deletions.
33 changes: 33 additions & 0 deletions api/courses.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ func configGinCourseRouter(router *gin.Engine, daoWrapper dao.DaoWrapper) {
lecturers.POST("/createCourse", routes.createCourse)
}

api.DELETE("/course/by-token/:courseID", routes.deleteCourseByToken)

courses := api.Group("/course/:courseID")
{
courses.Use(tools.InitCourse(daoWrapper))
Expand Down Expand Up @@ -1046,6 +1048,37 @@ func (r coursesRoutes) createCourse(c *gin.Context) {
c.JSON(http.StatusCreated, gin.H{"id": courseWithID.ID})
}

func (r coursesRoutes) deleteCourseByToken(c *gin.Context) {
tumLiveContext := c.MustGet("TUMLiveContext").(tools.TUMLiveContext)

err := c.Request.ParseForm()
if err != nil {
_ = c.AbortWithError(http.StatusBadRequest, tools.RequestError{Status: http.StatusBadRequest, CustomMessage: "invalid form", Err: err})
return
}
token := c.Request.Form.Get("token")
if token == "" {
_ = c.AbortWithError(http.StatusBadRequest, tools.RequestError{Status: http.StatusBadRequest, CustomMessage: "token is missing"})
return
}
course, err := r.CoursesDao.GetCourseByToken(token)
if err != nil {
_ = c.AbortWithError(http.StatusNotFound, tools.RequestError{Status: http.StatusNotFound, CustomMessage: "course not found", Err: err})
return
}

if err := r.AuditDao.Create(&model.Audit{
User: tumLiveContext.User,
Message: fmt.Sprintf("'%s' (%d, %s)[%d]. Token: %s", course.Name, course.Year, course.TeachingTerm, course.ID, token),
Type: model.AuditCourseDelete,
}); err != nil {
log.Error("Create Audit:", err)
}

r.CoursesDao.DeleteCourse(course)
dao.Cache.Clear()
}

func (r coursesRoutes) deleteCourse(c *gin.Context) {
tumLiveContext := c.MustGet("TUMLiveContext").(tools.TUMLiveContext)

Expand Down
4 changes: 2 additions & 2 deletions api/template/mail-course-registered.gotemplate
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Hallo {{.Name}},
Sie erhalten diese Nachricht, weil Sie als Verantwortliche/r in TUMOnline für den Kurs "{{.Course.Name}}" eingetragen sind, der in einem von uns mit Livestreaming-hardware ausgestatteten Raum statt findet. Sollten sie hierfür nicht verantwortlich sein können Sie diese Nachricht ignorieren.

Wir haben Ihren Kurs automatisch in unser System TUM-Live (live.rbg.tum.de) eingetragen. {{if .OptIn}}Wenn Sie Livestreams oder Aufzeichnungen Ihrer Veranstaltung wünschen, nutzen Sie bitte diesen Link zur Aktivierung:
https://live.rbg.tum.de/edit-course/?token={{.Course.Token}}{{end}}
https://live.rbg.tum.de/edit-course/?token={{.Course.Token}}{{else}}Sollten Sie keine Übertragung und Aufzeichnung wünschen nutzen Sie bitte diesen Link um die Veranstaltung zu entfernen: https://live.rbg.tum.de/edit-course/opt-out?token={{.Course.Token}}{{end}}

Abgesehen davon, dass ein Funkmikrofon verwendet werden muss, das Sie an der Pforte (00.01.010) erhalten ändert sich hierdurch am Ablauf der Veranstaltung nichts, sie wird zur gebuchten Zeit automatisch im Internet übertragen.
{{if not .OptIn}}Sie können die unten genannten Einstellungen ändern indem Sie sich bei https://live.rbg.tum.de/ mit Ihrer LRZ-Kennung anmelden und über den Admin Bereich zu Ihrem Kurs navigieren.{{end}}
Expand All @@ -22,7 +22,7 @@ Dear {{.Name}},
This message was sent to you because you are listed as responsible for the course "{{.Course.Name}}" in TUMOnline which will take place in a room equipped with our livestreaming hardware. If you are not responsible for this course feel free to ignore this message.

We registered your lectures in TUM-Live (live.rbg.tum.de) automatically. {{if .OptIn}}If you want them to be streamed or recorded, please activate it using this link:
https://live.rbg.tum.de/edit-course/?token={{.Course.Token}}{{end}}
https://live.rbg.tum.de/edit-course/?token={{.Course.Token}}{{else}}If you don't want your lectures to be streamed and recorded please use this link to opt out: https://live.rbg.tum.de/edit-course/opt-out?token={{.Course.Token}}{{end}}

Besides having to use a microphone which you can get at the reception (00.01.010), this doesn't affect your lecture. It will be streamed during the booked timeslot automatically.
{{if not .OptIn}}You can change the settings below by logging into https://live.rbg.tum.de/ using your LRZ-Id and navigating to your course in the admin tab.{{end}}
Expand Down
8 changes: 2 additions & 6 deletions dao/courses.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ func (d coursesDao) CreateCourse(ctx context.Context, course *model.Course, keep
return err
}
if !keep {
err = DB.Model(&course).Updates(map[string]interface{}{"live_enabled": "0"}).Error
if err != nil {
log.WithError(err).Error("Can't update live enabled state")
}
return DB.Delete(&course).Error
}
return nil
Expand Down Expand Up @@ -308,11 +304,11 @@ func (d coursesDao) DeleteCourse(course model.Course) {
log.WithError(err).Error("Can't delete stream")
}
}
err := DB.Model(&course).Updates(map[string]interface{}{"live_enabled": false, "vod_enabled": false}).Error
err := DB.Model(&course).Updates(map[string]interface{}{"vod_enabled": false}).Error
if err != nil {
log.WithError(err).Error("Can't update course settings when deleting")
}
err = DB.Delete(&course).Error
err = DB.Delete(&course, course.ID).Error
if err != nil {
log.WithError(err).Error("Can't delete course")
}
Expand Down
2 changes: 2 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
Expand Down Expand Up @@ -287,6 +288,7 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/fasthttp v1.6.0 h1:uWF8lgKmeaIewWVPwi4GRq2P6+R46IgYZdxWtM+GtEY=
Expand Down
2 changes: 1 addition & 1 deletion tools/middlewares.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func RenderErrorPage(c *gin.Context, status int, message string) {
c.Abort()
}

//ErrorPageData is the required data for the error page
// ErrorPageData is the required data for the error page
type ErrorPageData struct {
Status int
Message string
Expand Down
49 changes: 48 additions & 1 deletion web/course.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,18 @@ func (r mainRoutes) editCourseByTokenPage(c *gin.Context) {
c.AbortWithStatus(http.StatusBadRequest)
return
}
token := c.Request.Form.Get("token")
if token == "" {
_ = c.AbortWithError(http.StatusForbidden, tools.RequestError{
Status: http.StatusForbidden,
CustomMessage: "please provide a token",
Err: fmt.Errorf("token is empty"),
})
return
}

indexData := NewIndexDataWithContext(c)
course, err := r.CoursesDao.GetCourseByToken(c.Request.Form.Get("token"))
course, err := r.CoursesDao.GetCourseByToken(token)
if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "Course not found"})
return
Expand All @@ -47,6 +56,44 @@ func (r mainRoutes) editCourseByTokenPage(c *gin.Context) {
}
}

type OptOutPageData struct {
IndexData IndexData
Course *model.Course
}

func (r mainRoutes) optOutPage(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
_ = c.AbortWithError(http.StatusBadRequest, tools.RequestError{
Status: http.StatusBadRequest,
CustomMessage: "Could not read your request.",
Err: err,
})
}
token := c.Request.Form.Get("token")
if token == "" {
_ = c.AbortWithError(http.StatusForbidden, tools.RequestError{
Status: http.StatusForbidden,
CustomMessage: "please provide a token",
Err: fmt.Errorf("token is empty"),
})
return
}

var d OptOutPageData
d.IndexData = NewIndexData()
course, err := r.CoursesDao.GetCourseByToken(token)
if err != nil {
d.Course = nil
} else {
d.Course = &course
}
err = templateExecutor.ExecuteTemplate(c.Writer, "opt-out.gohtml", d)
if err != nil {
log.WithError(err).Error("can't render template")
}
}

func (r mainRoutes) HighlightPage(c *gin.Context) {
course, err := r.CoursesDao.GetCourseByShortLink(c.Param("shortLink"))
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions web/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func configMainRoute(router *gin.Engine) {

router.GET("/:shortLink", routes.HighlightPage)
router.GET("/edit-course", routes.editCourseByTokenPage)
router.GET("/edit-course/opt-out", routes.optOutPage)

// redirect from old site:
router.GET("/cgi-bin/streams/*x", func(c *gin.Context) {
Expand Down
35 changes: 35 additions & 0 deletions web/template/admin/opt-out.gohtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{- /*gotype: github.com/joschahenningsen/TUM-Live/web.OptOutPageData*/ -}}
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<title>Edit Course | TUM Live</title>
{{template "headImports" .IndexData.VersionTag}}
</head>

<body x-data>
{{template "header" .IndexData.TUMLiveContext}}
{{if and .Course (not .Course.Model.DeletedAt.Valid)}}
<div class="text-1 container mx-auto w-full" x-data="{success: false}">
<p x-show="!success">
Please confirm deleting the course <span class="font-semibold">{{.Course.Name}}</span>.
<br>
This will disable live-streaming and recordings of your lectures.
<br>
<button class="mt-4 w-auto m-auto bg-danger rounded px-5 py-2 font-semibold text-white"
@click="fetch('/api/course/by-token/{{.Course.Model.ID}}?token='+(new URLSearchParams(window.location.search)).get('token'), {method: 'DELETE'}).then(r=>{if(r.status===200){success=true;}else{alert('Something went wrong, please reach out to us.')}})">
Confirm
</button>
</p>
<p x-show="success" class="font-semibold">
Your course was deleted successfully.
</p>
</div>
{{else}}
<p class="text-1 container mx-auto w-full">
There was an issue finding your course. Maybe you already opted out. If not please reach out to us.
</p>
{{end}}
</body>

</html>

0 comments on commit d94bd67

Please sign in to comment.