From b6fd694820bc953ed443e7d86941f1034de7abf0 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sun, 11 Nov 2018 21:18:37 -0700
Subject: [PATCH] Have upload exclusions be glob matches on users

---
 config.sample.yaml                            | 13 +++--
 .../matrix-media-repo/common/config/config.go |  2 +-
 .../upload_controller/upload_controller.go    | 47 ++++++++++++-------
 3 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/config.sample.yaml b/config.sample.yaml
index ac7fd945..0d04119b 100644
--- a/config.sample.yaml
+++ b/config.sample.yaml
@@ -50,13 +50,18 @@ uploads:
   allowedTypes:
    - "*/*"
 
-  # If not all file types are allowed, then you can make an exlusion for some users. So 
-  # that users can upload file types that not allowed to others.
+  # Specific users can have their own set of allowed file types. These are applied instead
+  # of those listed in the allowedTypes list when a user is found. Much like allowedTypes,
+  # asterisks may be used in the content types and may also be used in the user IDs. This
+  # allows for entire servers to have different allowed types by setting a rule similar to
+  # "@*:example.org". Users will be allowed to upload a file if the type matches any of
+  # the policies that match the user ID.
   #exclusions:
-  #  "@admin1:matrix.org":
+  #  "@someone:example.org":
   #     - "application/pdf"
   #     - "application/vnd.ms-excel"
-  #  "@admin2:matrix.org": [*/*]
+  #  "@*:example.org":
+  #     - "*/*"
 
 
 # Settings related to downloading files from the media repository
diff --git a/src/github.com/turt2live/matrix-media-repo/common/config/config.go b/src/github.com/turt2live/matrix-media-repo/common/config/config.go
index feb12405..587911be 100644
--- a/src/github.com/turt2live/matrix-media-repo/common/config/config.go
+++ b/src/github.com/turt2live/matrix-media-repo/common/config/config.go
@@ -35,7 +35,7 @@ type UploadsConfig struct {
 	StoragePaths         []string            `yaml:"storagePaths,flow"`
 	MaxSizeBytes         int64               `yaml:"maxBytes"`
 	AllowedTypes         []string            `yaml:"allowedTypes,flow"`
-	AllowedExcl          map[string][]string `yaml:"exclusions,flow"`
+	PerUserExclusions    map[string][]string `yaml:"exclusions,flow"`
 	ReportedMaxSizeBytes int64               `yaml:"reportedMaxBytes"`
 }
 
diff --git a/src/github.com/turt2live/matrix-media-repo/controllers/upload_controller/upload_controller.go b/src/github.com/turt2live/matrix-media-repo/controllers/upload_controller/upload_controller.go
index 0ed04662..84cafc10 100644
--- a/src/github.com/turt2live/matrix-media-repo/controllers/upload_controller/upload_controller.go
+++ b/src/github.com/turt2live/matrix-media-repo/controllers/upload_controller/upload_controller.go
@@ -76,30 +76,41 @@ func StoreDirect(contents io.Reader, contentType string, filename string, userId
 	}
 
 	allowed := false
-	for _, allowedType := range config.Get().Uploads.AllowedTypes {
-		if glob.Glob(allowedType, fileMime) {
-			allowed = true
-		}
-	}
-	if !allowed {
-		exclusion := false
-		for user, userExcl := range config.Get().Uploads.AllowedExcl {
-			if user == userId {
-				for _, exclType := range userExcl {
-					if glob.Glob(exclType, fileMime){
-						exclusion = true
-						log.Info("Content type " + fileMime +" (reported as " + contentType+") is allowed to be uploaded as exclusion for user "+ userId)
-					}
+	userMatched := false
+	for user, userExcl := range config.Get().Uploads.PerUserExclusions {
+		if glob.Glob(user, userId) {
+			if !userMatched {
+				log.Info("Per-user allowed types policy found for " + userId)
+				userMatched = true
+			}
+			for _, exclType := range userExcl {
+				if glob.Glob(exclType, fileMime) {
+					allowed = true
+					log.Info("Content type " + fileMime + " (reported as " + contentType + ") is allowed due to a per-user policy for " + userId)
+					break
 				}
 			}
 		}
-		if !exclusion {
-			log.Warn("Content type " + fileMime +" (reported as " + contentType+") is not allowed to be uploaded")
 
-			os.Remove(fileLocation) // delete temp file
-			return nil, common.ErrMediaNotAllowed
+		if allowed {
+			break
+		}
+	}
+	if !userMatched && !allowed {
+		log.Info("Checking general allowed types due to no matching per-user policy")
+		for _, allowedType := range config.Get().Uploads.AllowedTypes {
+			if glob.Glob(allowedType, fileMime) {
+				allowed = true
+				break
+			}
 		}
 	}
+	if !allowed {
+		log.Warn("Content type " + fileMime + " (reported as " + contentType + ") is not allowed to be uploaded")
+
+		os.Remove(fileLocation) // delete temp file
+		return nil, common.ErrMediaNotAllowed
+	}
 
 	hash, err := storage.GetFileHash(fileLocation)
 	if err != nil {
-- 
GitLab