diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/auth.go b/src/github.com/turt2live/matrix-media-repo/api/auth.go similarity index 68% rename from src/github.com/turt2live/matrix-media-repo/api/r0/auth.go rename to src/github.com/turt2live/matrix-media-repo/api/auth.go index fc8b18b2e1f7bbf25c414fee6e8dd03345bebc29..d8fe4a61b12654a3d50b3f19296c121295ba4b66 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/auth.go +++ b/src/github.com/turt2live/matrix-media-repo/api/auth.go @@ -1,20 +1,19 @@ -package r0 +package api import ( "net/http" "github.com/sirupsen/logrus" - "github.com/turt2live/matrix-media-repo/api" "github.com/turt2live/matrix-media-repo/matrix" "github.com/turt2live/matrix-media-repo/util" ) -type userInfo struct { - userId string - accessToken string +type UserInfo struct { + UserId string + AccessToken string } -func AccessTokenRequiredRoute(next func(r *http.Request, log *logrus.Entry, user userInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { +func AccessTokenRequiredRoute(next func(r *http.Request, log *logrus.Entry, user UserInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { return func(r *http.Request, log *logrus.Entry) interface{} { accessToken := util.GetAccessTokenFromRequest(r) appserviceUserId := util.GetAppserviceUserIdFromRequest(r) @@ -23,19 +22,19 @@ func AccessTokenRequiredRoute(next func(r *http.Request, log *logrus.Entry, user log.Error(err) if err != nil && err != matrix.ErrNoToken { log.Error("Error verifying token: ", err) - return api.InternalServerError("Unexpected Error") + return InternalServerError("Unexpected Error") } log.Warn("Failed to verify token (fatal)") - return api.AuthFailed() + return AuthFailed() } log = log.WithFields(logrus.Fields{"authUserId": userId}) - return next(r, log, userInfo{userId, accessToken}) + return next(r, log, UserInfo{userId, accessToken}) } } -func AccessTokenOptionalRoute(next func(r *http.Request, log *logrus.Entry, user userInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { +func AccessTokenOptionalRoute(next func(r *http.Request, log *logrus.Entry, user UserInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { return func(r *http.Request, log *logrus.Entry) interface{} { accessToken := util.GetAccessTokenFromRequest(r) appserviceUserId := util.GetAppserviceUserIdFromRequest(r) @@ -43,7 +42,7 @@ func AccessTokenOptionalRoute(next func(r *http.Request, log *logrus.Entry, user if err != nil { if err != matrix.ErrNoToken { log.Error("Error verifying token: ", err) - return api.InternalServerError("Unexpected Error") + return InternalServerError("Unexpected Error") } log.Warn("Failed to verify token (non-fatal)") @@ -51,19 +50,19 @@ func AccessTokenOptionalRoute(next func(r *http.Request, log *logrus.Entry, user } log = log.WithFields(logrus.Fields{"authUserId": userId}) - return next(r, log, userInfo{userId, accessToken}) + return next(r, log, UserInfo{userId, accessToken}) } } -func RepoAdminRoute(next func(r *http.Request, log *logrus.Entry, user userInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { - return AccessTokenRequiredRoute(func(r *http.Request, log *logrus.Entry, user userInfo) interface{} { - if user.userId == "" { +func RepoAdminRoute(next func(r *http.Request, log *logrus.Entry, user UserInfo) interface{}) func(*http.Request, *logrus.Entry) interface{} { + return AccessTokenRequiredRoute(func(r *http.Request, log *logrus.Entry, user UserInfo) interface{} { + if user.UserId == "" { log.Warn("Could not identify user for this admin route") - return api.AuthFailed() + return AuthFailed() } - if !util.IsGlobalAdmin(user.userId) { - log.Warn("User " + user.userId + " is not a repository administrator") - return api.AuthFailed() + if !util.IsGlobalAdmin(user.UserId) { + log.Warn("User " + user.UserId + " is not a repository administrator") + return AuthFailed() } log = log.WithFields(logrus.Fields{"isRepoAdmin": true}) diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/download.go b/src/github.com/turt2live/matrix-media-repo/api/r0/download.go index 2609928a132965ac5d50f9b48162c66d87c95785..a6e5460da790a80a2c54f75a33478f5fe5a398df 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/download.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/download.go @@ -19,9 +19,9 @@ type DownloadMediaResponse struct { Data io.ReadCloser } -func DownloadMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func DownloadMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { hs := util.GetHomeserverConfig(r.Host) - if hs.DownloadRequiresAuth && user.userId == "" { + if hs.DownloadRequiresAuth && user.UserId == "" { log.Warn("Homeserver requires authenticated downloads - denying request") return api.AuthFailed() } diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/identicon.go b/src/github.com/turt2live/matrix-media-repo/api/r0/identicon.go index 9a39a49a478c5f18db2dcb25a8cc2799cbe01347..82f2ab76743530b18590b3073325ded949886add 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/identicon.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/identicon.go @@ -21,9 +21,9 @@ type IdenticonResponse struct { Avatar io.Reader } -func Identicon(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func Identicon(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { hs := util.GetHomeserverConfig(r.Host) - if hs.DownloadRequiresAuth && user.userId == "" { + if hs.DownloadRequiresAuth && user.UserId == "" { log.Warn("Homeserver requires authenticated downloads - denying request") return api.AuthFailed() } diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/info.go b/src/github.com/turt2live/matrix-media-repo/api/r0/info.go index a241c69fbe5542d97fbd9744da643654b098bef3..6624241b76529c4502d6c538d903de7279a99b67 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/info.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/info.go @@ -19,7 +19,7 @@ type MediaInfoResponse struct { Size int64 `json:"size"` } -func MediaInfo(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func MediaInfo(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { params := mux.Vars(r) server := params["server"] diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/local_copy.go b/src/github.com/turt2live/matrix-media-repo/api/r0/local_copy.go index e00da83e3f019b1541722ddda5e658e267d4d726..a3148ed105c5a94a2573f6fd50bc87c74bacd897 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/local_copy.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/local_copy.go @@ -11,7 +11,7 @@ import ( "github.com/turt2live/matrix-media-repo/util/errs" ) -func LocalCopy(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func LocalCopy(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { params := mux.Vars(r) server := params["server"] @@ -46,7 +46,7 @@ func LocalCopy(r *http.Request, log *logrus.Entry, user userInfo) interface{} { return &MediaUploadedResponse{streamedMedia.Media.MxcUri()} } - newMedia, err := svc.StoreMedia(streamedMedia.Stream, streamedMedia.Media.ContentType, streamedMedia.Media.UploadName, user.userId, r.Host, "") + newMedia, err := svc.StoreMedia(streamedMedia.Stream, streamedMedia.Media.ContentType, streamedMedia.Media.UploadName, user.UserId, r.Host, "") if err != nil { if err == errs.ErrMediaNotAllowed { return api.BadRequest("Media content type not allowed on this server") diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/preview_url.go b/src/github.com/turt2live/matrix-media-repo/api/r0/preview_url.go index e52d7ad359bce32c64d049927fdd91a1a0d7a1c3..fdc80bae619505c94a5a320d1d1ab12a5858e317 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/preview_url.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/preview_url.go @@ -26,7 +26,7 @@ type MatrixOpenGraph struct { ImageHeight int `json:"og:image:height,omitempty"` } -func PreviewUrl(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func PreviewUrl(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { if !config.Get().UrlPreviews.Enabled { return api.NotFoundError() } @@ -55,7 +55,7 @@ func PreviewUrl(r *http.Request, log *logrus.Entry, user userInfo) interface{} { } svc := url_service.New(r.Context(), log) - preview, err := svc.GetPreview(urlStr, r.Host, user.userId, ts) + preview, err := svc.GetPreview(urlStr, r.Host, user.UserId, ts) if err != nil { if err == errs.ErrMediaNotFound || err == errs.ErrHostNotFound { return api.NotFoundError() diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/purge.go b/src/github.com/turt2live/matrix-media-repo/api/r0/purge.go index 2fcc2ab2b06ee1e92df455d35ef492c637c99764..18049839271057ff20bf70a6026d808d7cbbd74c 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/purge.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/purge.go @@ -13,7 +13,7 @@ type MediaPurgedResponse struct { NumRemoved int `json:"total_removed"` } -func PurgeRemoteMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func PurgeRemoteMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { beforeTsStr := r.URL.Query().Get("before_ts") if beforeTsStr == "" { return api.BadRequest("Missing before_ts argument") diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/quarantine.go b/src/github.com/turt2live/matrix-media-repo/api/r0/quarantine.go index 79da321cd1e3bde935328e59602245c10ff2ae66..7c21027c5cdd36549b84aafbd2293f98d79caff2 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/quarantine.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/quarantine.go @@ -18,7 +18,7 @@ type MediaQuarantinedResponse struct { NumQuarantined int `json:"num_quarantined"` } -func QuarantineRoomMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func QuarantineRoomMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user) if !canQuarantine { return api.AuthFailed() @@ -33,7 +33,7 @@ func QuarantineRoomMedia(r *http.Request, log *logrus.Entry, user userInfo) inte "localAdmin": isLocalAdmin, }) - allMedia, err := matrix.ListMedia(r.Context(), r.Host, user.accessToken, roomId) + allMedia, err := matrix.ListMedia(r.Context(), r.Host, user.AccessToken, roomId) if err != nil { log.Error("Error while listing media in the room: " + err.Error()) return api.InternalServerError("error retrieving media in room") @@ -67,7 +67,7 @@ func QuarantineRoomMedia(r *http.Request, log *logrus.Entry, user userInfo) inte return &MediaQuarantinedResponse{NumQuarantined: total} } -func QuarantineMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func QuarantineMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user) if !canQuarantine { return api.AuthFailed() @@ -115,15 +115,15 @@ func doQuarantine(ctx context.Context, log *logrus.Entry, server string, mediaId return &MediaQuarantinedResponse{NumQuarantined: num}, true } -func getQuarantineRequestInfo(r *http.Request, log *logrus.Entry, user userInfo) (bool, bool, bool) { - isGlobalAdmin := util.IsGlobalAdmin(user.userId) +func getQuarantineRequestInfo(r *http.Request, log *logrus.Entry, user api.UserInfo) (bool, bool, bool) { + isGlobalAdmin := util.IsGlobalAdmin(user.UserId) canQuarantine := isGlobalAdmin allowOtherHosts := isGlobalAdmin isLocalAdmin := false var err error if !isGlobalAdmin { if config.Get().Quarantine.AllowLocalAdmins { - isLocalAdmin, err = matrix.IsUserAdmin(r.Context(), r.Host, user.accessToken) + isLocalAdmin, err = matrix.IsUserAdmin(r.Context(), r.Host, user.AccessToken) if err != nil { log.Error("Error verifying local admin: " + err.Error()) canQuarantine = false @@ -131,7 +131,7 @@ func getQuarantineRequestInfo(r *http.Request, log *logrus.Entry, user userInfo) } if !isLocalAdmin { - log.Warn(user.userId + " tried to quarantine media on another server") + log.Warn(user.UserId + " tried to quarantine media on another server") canQuarantine = false return canQuarantine, allowOtherHosts, isLocalAdmin } @@ -142,7 +142,7 @@ func getQuarantineRequestInfo(r *http.Request, log *logrus.Entry, user userInfo) } if !canQuarantine { - log.Warn(user.userId + " tried to quarantine media") + log.Warn(user.UserId + " tried to quarantine media") } return canQuarantine, allowOtherHosts, isLocalAdmin diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/thumbnail.go b/src/github.com/turt2live/matrix-media-repo/api/r0/thumbnail.go index e7f65eb9f2b34b4e90fc7b981a4e4483c19442b0..8b68fd44172b7caae4e1af733255fadb2e0706c2 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/thumbnail.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/thumbnail.go @@ -13,9 +13,9 @@ import ( "github.com/turt2live/matrix-media-repo/util/errs" ) -func ThumbnailMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func ThumbnailMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { hs := util.GetHomeserverConfig(r.Host) - if hs.DownloadRequiresAuth && user.userId == "" { + if hs.DownloadRequiresAuth && user.UserId == "" { log.Warn("Homeserver requires authenticated downloads - denying request") return api.AuthFailed() } diff --git a/src/github.com/turt2live/matrix-media-repo/api/r0/upload.go b/src/github.com/turt2live/matrix-media-repo/api/r0/upload.go index d731b7df6ac7133aa10aa4942c407093bf543112..1ae677ed2fd96915bee2f9b07c5d514dacb92908 100644 --- a/src/github.com/turt2live/matrix-media-repo/api/r0/upload.go +++ b/src/github.com/turt2live/matrix-media-repo/api/r0/upload.go @@ -15,7 +15,7 @@ type MediaUploadedResponse struct { ContentUri string `json:"content_uri"` } -func UploadMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} { +func UploadMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { filename := r.URL.Query().Get("filename") if filename == "" { filename = "upload.bin" @@ -38,7 +38,7 @@ func UploadMedia(r *http.Request, log *logrus.Entry, user userInfo) interface{} return api.RequestTooLarge() } - media, err := svc.UploadMedia(r.Body, contentType, filename, user.userId, r.Host) + media, err := svc.UploadMedia(r.Body, contentType, filename, user.UserId, r.Host) if err != nil { io.Copy(ioutil.Discard, r.Body) // Ditch the entire request defer r.Body.Close() diff --git a/src/github.com/turt2live/matrix-media-repo/cmd/media_repo/main.go b/src/github.com/turt2live/matrix-media-repo/cmd/media_repo/main.go index c14c35f66f5555e416d5030cab40dd0c2e63bc81..9bf3ec6f05d23c31433ae1aac699fe012e6892c7 100644 --- a/src/github.com/turt2live/matrix-media-repo/cmd/media_repo/main.go +++ b/src/github.com/turt2live/matrix-media-repo/cmd/media_repo/main.go @@ -66,16 +66,16 @@ func main() { hOpts := HandlerOpts{&counter} optionsHandler := Handler{optionsRequest, hOpts} - uploadHandler := Handler{r0.AccessTokenRequiredRoute(r0.UploadMedia), hOpts} - downloadHandler := Handler{r0.AccessTokenOptionalRoute(r0.DownloadMedia), hOpts} - thumbnailHandler := Handler{r0.AccessTokenOptionalRoute(r0.ThumbnailMedia), hOpts} - previewUrlHandler := Handler{r0.AccessTokenRequiredRoute(r0.PreviewUrl), hOpts} - identiconHandler := Handler{r0.AccessTokenOptionalRoute(r0.Identicon), hOpts} - purgeHandler := Handler{r0.RepoAdminRoute(r0.PurgeRemoteMedia), hOpts} - quarantineHandler := Handler{r0.AccessTokenRequiredRoute(r0.QuarantineMedia), hOpts} - quarantineRoomHandler := Handler{r0.AccessTokenRequiredRoute(r0.QuarantineRoomMedia), hOpts} - localCopyHandler := Handler{r0.AccessTokenRequiredRoute(r0.LocalCopy), hOpts} - infoHandler := Handler{r0.AccessTokenRequiredRoute(r0.MediaInfo), hOpts} + uploadHandler := Handler{api.AccessTokenRequiredRoute(r0.UploadMedia), hOpts} + downloadHandler := Handler{api.AccessTokenOptionalRoute(r0.DownloadMedia), hOpts} + thumbnailHandler := Handler{api.AccessTokenOptionalRoute(r0.ThumbnailMedia), hOpts} + previewUrlHandler := Handler{api.AccessTokenRequiredRoute(r0.PreviewUrl), hOpts} + identiconHandler := Handler{api.AccessTokenOptionalRoute(r0.Identicon), hOpts} + purgeHandler := Handler{api.RepoAdminRoute(r0.PurgeRemoteMedia), hOpts} + quarantineHandler := Handler{api.AccessTokenRequiredRoute(r0.QuarantineMedia), hOpts} + quarantineRoomHandler := Handler{api.AccessTokenRequiredRoute(r0.QuarantineRoomMedia), hOpts} + localCopyHandler := Handler{api.AccessTokenRequiredRoute(r0.LocalCopy), hOpts} + infoHandler := Handler{api.AccessTokenRequiredRoute(r0.MediaInfo), hOpts} routes := make(map[string]*ApiRoute) versions := []string{"r0", "v1"} // r0 is typically clients and v1 is typically servers