Advertisement
Guest User

Untitled

a guest
Nov 19th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 9.36 KB | None | 0 0
  1. package upload
  2.  
  3. import (
  4.     "crypto/md5"
  5.     "crypto/sha1"
  6.     "crypto/sha256"
  7.     "crypto/sha512"
  8.     "encoding/json"
  9.     "fmt"
  10.     "io"
  11.     "net/http"
  12.     "os"
  13.     "strconv"
  14.     "strings"
  15.  
  16.     "github.com/subutai-io/agent/log"
  17.     "github.com/subutai-io/gorjun/config"
  18.     "github.com/subutai-io/gorjun/db"
  19. )
  20.  
  21. type share struct {
  22.     Token  string   `json:"token"`
  23.     Id     string   `json:"id"`
  24.     Add    []string `json:"add"`
  25.     Remove []string `json:"remove"`
  26.     Repo   string   `json:"repo"`
  27. }
  28.  
  29. //Handler function works with income upload requests, makes sanity checks, etc
  30. func Handler(w http.ResponseWriter, r *http.Request) (md5sum, sha256sum, owner string) {
  31.     token := r.Header.Get("token")
  32.     owner = strings.ToLower(db.CheckToken(token))
  33.     if len(token) == 0 || len(owner) == 0 {
  34.         w.WriteHeader(http.StatusUnauthorized)
  35.         w.Write([]byte("Not authorized"))
  36.         log.Warn(r.RemoteAddr + " - rejecting unauthorized upload request")
  37.         return
  38.     }
  39.     r.ParseMultipartForm(32 << 20)
  40.  
  41.     file, header, err := r.FormFile("file")
  42.     if log.Check(log.WarnLevel, "Failed to parse POST form", err) {
  43.         w.WriteHeader(http.StatusBadRequest)
  44.         w.Write([]byte("Cannot get file from request"))
  45.         return
  46.     }
  47.     defer file.Close()
  48.  
  49.     if !сheckLength(owner, r.Header.Get("Content-Length")) {
  50.         w.WriteHeader(http.StatusNotAcceptable)
  51.         w.Write([]byte("Storage quota exceeded"))
  52.         log.Warn("User " + owner + " exceeded storage quota, rejecting upload")
  53.         return
  54.     }
  55.  
  56.     out, err := os.Create(config.Storage.Path + header.Filename)
  57.     if log.Check(log.WarnLevel, "Unable to create the file for writing", err) {
  58.         w.WriteHeader(http.StatusInternalServerError)
  59.         w.Write([]byte("Cannot create file"))
  60.         return
  61.     }
  62.     defer out.Close()
  63.  
  64.     limit := int64(db.QuotaLeft(owner))
  65.     f := io.Reader(file)
  66.     if limit != -1 {
  67.         f = io.LimitReader(file, limit)
  68.     }
  69.  
  70.     // write the content from POST to the file
  71.     if copied, err := io.Copy(out, f); limit != -1 && (copied == limit || err != nil) {
  72.         w.WriteHeader(http.StatusInternalServerError)
  73.         w.Write([]byte("Failed to write file or storage quota exceeded"))
  74.         log.Warn("User " + owner + " exceeded storage quota, removing file")
  75.         os.Remove(config.Storage.Path + header.Filename)
  76.         return
  77.     } else {
  78.         db.QuotaUsageSet(owner, int(copied))
  79.         log.Info("User " + owner + ", quota usage +" + strconv.Itoa(int(copied)))
  80.     }
  81.  
  82.     md5sum = Hash(config.Storage.Path + header.Filename)
  83.     sha256sum = Hash(config.Storage.Path+header.Filename, "sha256")
  84.     if len(md5sum) == 0 || len(sha256sum) == 0 {
  85.         log.Warn("Failed to calculate hash for " + header.Filename)
  86.         w.WriteHeader(http.StatusInternalServerError)
  87.         w.Write([]byte("Failed to calculate hash"))
  88.         return
  89.     }
  90.  
  91.     os.Rename(config.Storage.Path+header.Filename, config.Storage.Path+md5sum)
  92.     log.Info("File received: " + header.Filename + "(" + md5sum + ")")
  93.  
  94.     return md5sum, sha256sum, owner
  95. }
  96.  
  97. func Hash(file string, algo ...string) string {
  98.     f, err := os.Open(file)
  99.     log.Check(log.WarnLevel, "Opening file "+file, err)
  100.     defer f.Close()
  101.  
  102.     hash := md5.New()
  103.     if len(algo) != 0 {
  104.         switch algo[0] {
  105.         case "sha512":
  106.             hash = sha512.New()
  107.         case "sha256":
  108.             hash = sha256.New()
  109.         case "sha1":
  110.             hash = sha1.New()
  111.         }
  112.     }
  113.     if _, err := io.Copy(hash, f); err != nil {
  114.         return ""
  115.     }
  116.     return fmt.Sprintf("%x", hash.Sum(nil))
  117. }
  118.  
  119. func Delete(w http.ResponseWriter, r *http.Request) string {
  120.     id := r.URL.Query().Get("id")
  121.     token := r.URL.Query().Get("token")
  122.     if len(id) == 0 {
  123.         w.WriteHeader(http.StatusBadRequest)
  124.         w.Write([]byte("Empty file id"))
  125.         log.Warn(r.RemoteAddr + " - empty file id")
  126.         return ""
  127.     }
  128.     user := db.CheckToken(token)
  129.     if len(token) == 0 || len(user) == 0 {
  130.         w.WriteHeader(http.StatusUnauthorized)
  131.         w.Write([]byte("Failed to authorize using provided token"))
  132.         log.Warn(r.RemoteAddr + " - Failed to authorize using provided token")
  133.         return ""
  134.     }
  135.     info := db.Info(id)
  136.     if len(info) == 0 {
  137.         log.Warn("File not found by id")
  138.         w.WriteHeader(http.StatusNotFound)
  139.         w.Write([]byte("File not found"))
  140.         return ""
  141.     }
  142.  
  143.     repo := strings.Split(r.URL.EscapedPath(), "/")
  144.     if len(repo) < 4 {
  145.         log.Warn(r.URL.EscapedPath() + " - bad deletion request")
  146.         w.WriteHeader(http.StatusBadRequest)
  147.         w.Write([]byte("Bad request"))
  148.         return ""
  149.     }
  150.  
  151.     if db.CheckRepo(user, repo[3], id) == 0 {
  152.         log.Warn("File " + info["name"] + "(" + id + ") in " + repo[3] + " repo is not owned by " + user + ", rejecting deletion request")
  153.         w.WriteHeader(http.StatusNotFound)
  154.         w.Write([]byte("File " + info["name"] + " not found or it has different owner"))
  155.         return ""
  156.     }
  157.     md5, _ := db.Hash(id)
  158.     f, err := os.Stat(config.Storage.Path + md5)
  159.     if !log.Check(log.WarnLevel, "Reading file stats", err) {
  160.         db.QuotaUsageSet(user, -int(f.Size()))
  161.         log.Info("User " + user + ", quota usage -" + strconv.Itoa(int(f.Size())))
  162.     }
  163.  
  164.     if db.Delete(user, repo[3], id) == 0 {
  165.         log.Warn("Removing " + id + " from disk")
  166.         // torrent.Delete(id)
  167.         if log.Check(log.WarnLevel, "Removing "+info["name"]+"from disk", os.Remove(config.Storage.Path+md5)) {
  168.             w.WriteHeader(http.StatusInternalServerError)
  169.             w.Write([]byte("Failed to remove file"))
  170.             return ""
  171.         }
  172.     }
  173.  
  174.     log.Info("Removing " + info["name"] + " from " + repo[3] + " repo")
  175.     return id
  176. }
  177.  
  178. func Share(w http.ResponseWriter, r *http.Request) {
  179.     if r.Method == "POST" {
  180.         if len(r.FormValue("json")) == 0 {
  181.             w.WriteHeader(http.StatusBadRequest)
  182.             w.Write([]byte("Empty json"))
  183.             log.Warn("Share request: empty json, nothing to do")
  184.             return
  185.         }
  186.         var data share
  187.         if log.Check(log.WarnLevel, "Parsing share request json", json.Unmarshal([]byte(r.FormValue("json")), &data)) {
  188.             w.WriteHeader(http.StatusBadRequest)
  189.             w.Write([]byte("Failed to parse json body"))
  190.             return
  191.         }
  192.         if len(data.Token) == 0 || len(db.CheckToken(data.Token)) == 0 {
  193.             w.WriteHeader(http.StatusUnauthorized)
  194.             w.Write([]byte("Not authorized"))
  195.             log.Warn("Empty or invalid token, rejecting share request")
  196.             return
  197.         }
  198.         if len(data.Id) == 0 {
  199.             w.WriteHeader(http.StatusBadRequest)
  200.             w.Write([]byte("Empty file id"))
  201.             log.Warn("Empty file id, rejecting share request")
  202.             return
  203.         }
  204.         if len(data.Repo) == 0 {
  205.             w.WriteHeader(http.StatusBadRequest)
  206.             w.Write([]byte("Empty repo name"))
  207.             log.Warn("Empty repo name, rejecting share request")
  208.             return
  209.         }
  210.         owner := strings.ToLower(db.CheckToken(data.Token))
  211.         if db.CheckRepo(owner, data.Repo, data.Id) == 0 {
  212.             w.WriteHeader(http.StatusForbidden)
  213.             w.Write([]byte("File is not owned by authorized user"))
  214.             log.Warn("User tried to share another's file, rejecting")
  215.             return
  216.         }
  217.         for _, v := range data.Add {
  218.             log.Info("Sharing " + data.Id + " with " + v)
  219.             db.ShareWith(data.Id, owner, v)
  220.         }
  221.         for _, v := range data.Remove {
  222.             log.Info("Unsharing " + data.Id + " with " + v)
  223.             db.UnshareWith(data.Id, owner, v)
  224.         }
  225.     } else if r.Method == "GET" {
  226.         id := r.URL.Query().Get("id")
  227.         if len(id) == 0 {
  228.             w.WriteHeader(http.StatusBadRequest)
  229.             w.Write([]byte("Empty file id"))
  230.             return
  231.         }
  232.         token := r.URL.Query().Get("token")
  233.         if len(token) == 0 || len(db.CheckToken(token)) == 0 {
  234.             w.WriteHeader(http.StatusUnauthorized)
  235.             w.Write([]byte("Not authorized"))
  236.             return
  237.         }
  238.         owner := db.CheckToken(token)
  239.         repo := r.URL.Query().Get("repo")
  240.         if len(repo) == 0 {
  241.             w.WriteHeader(http.StatusUnauthorized)
  242.             w.Write([]byte("Repository not specified"))
  243.             return
  244.         }
  245.         if db.CheckRepo(owner, repo, id) == 0 {
  246.             w.WriteHeader(http.StatusForbidden)
  247.             w.Write([]byte("File is not owned by authorized user"))
  248.             log.Warn("User tried to request scope of another's file, rejecting")
  249.             return
  250.         }
  251.         js, _ := json.Marshal(db.GetScope(id, strings.ToLower(owner)))
  252.         w.Write(js)
  253.     }
  254. }
  255.  
  256. func сheckLength(user, length string) bool {
  257.     l, err := strconv.Atoi(length)
  258.     if err != nil || len(length) == 0 || l < db.QuotaLeft(user) || db.QuotaLeft(user) == -1 {
  259.         return true
  260.     }
  261.     return false
  262. }
  263.  
  264. func Quota(w http.ResponseWriter, r *http.Request) {
  265.     if r.Method == "GET" {
  266.         user := r.URL.Query().Get("user")
  267.         fix := r.URL.Query().Get("fix")
  268.         token := r.URL.Query().Get("token")
  269.  
  270.         if len(token) == 0 || len(db.CheckToken(token)) == 0 || db.CheckToken(token) != "Hub" && !strings.EqualFold(db.CheckToken(token), user) {
  271.             w.Write([]byte("Forbidden"))
  272.             w.WriteHeader(http.StatusForbidden)
  273.             return
  274.         }
  275.  
  276.         if len(user) != 0 {
  277.             user = strings.ToLower(user)
  278.             q, _ := json.Marshal(map[string]int{
  279.                 "quota": db.QuotaGet(user),
  280.                 "used":  db.QuotaUsageGet(user),
  281.                 "left":  db.QuotaLeft(user)})
  282.             w.Write([]byte(q))
  283.         }
  284.         if user == "subutai" && len(fix) != 0 {
  285.             db.QuotaUsageCorrect()
  286.         }
  287.  
  288.     } else if r.Method == "POST" {
  289.         user := r.FormValue("user")
  290.         quota := r.FormValue("quota")
  291.         token := r.FormValue("token")
  292.  
  293.         if len(token) == 0 || len(db.CheckToken(token)) == 0 || db.CheckToken(token) != "Hub" && db.CheckToken(token) != "subutai" {
  294.             w.Write([]byte("Forbidden"))
  295.             w.WriteHeader(http.StatusForbidden)
  296.             return
  297.         }
  298.  
  299.         if len(user) == 0 || len(quota) == 0 {
  300.             w.Write([]byte("Please specify username and quota value"))
  301.             w.WriteHeader(http.StatusBadRequest)
  302.             return
  303.         }
  304.  
  305.         if q, err := strconv.Atoi(quota); err != nil || q < -1 {
  306.             w.Write([]byte("Invalid quota value"))
  307.             w.WriteHeader(http.StatusBadRequest)
  308.             return
  309.         }
  310.  
  311.         db.QuotaSet(user, quota)
  312.         log.Info("New quota for " + user + " is " + quota)
  313.         w.Write([]byte("Ok"))
  314.         w.WriteHeader(http.StatusOK)
  315.     }
  316. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement