scala-news-reader

rss/atom news reader in scala

git clone https://9o.is/git/scala-news-reader.git

ImageUpload.scala

(4689B)


      1 package com.joereader.lib
      2 
      3 import net.liftweb._
      4 import http._, rest._, js.JsCmds.Run
      5 import common._
      6 import util._
      7 
      8 import com.joereader._
      9 import lib.aws._
     10 import config.S3Config._
     11 import model._
     12 import snippet.SnipHelpers.{imgBgId, imgProfileId, UpdateImage}
     13 
     14 import scala.concurrent._, ExecutionContext.Implicits.global
     15 import scala.concurrent.duration._
     16 
     17 object ImageUpload extends RestHelper with Logger {
     18 
     19   val nameLength = 32
     20   val acceptedImages = "image/jpeg" :: "image/png" :: "image/svg+xml" :: Nil
     21 
     22   val s3 = new S3(s3_access_key.get, s3_secret_key.get, s3_bucket.get)
     23 
     24   // indicates what kind of image
     25   // "bg" is background and "pic" is profile picture
     26   object ImageType extends Enumeration {
     27     type ImageType = Value
     28     val bg, pic = Value
     29   }
     30   import ImageType._
     31     
     32   // avoids accidently removing files like default backgrounds
     33   def deleteFile(fn: String) {
     34     if(fn.length == ImageUpload.nameLength) 
     35       s3.deleteFile(fn)
     36   }
     37 
     38   def userUrl(imgType: ImageType) =
     39     "/api/image/upload/user?type=" + imgType
     40 
     41   def blogUrl(blog: Blog, imgType: ImageType) =
     42     "/api/image/upload/blog/" + blog.id.get + "?type=" + imgType
     43 
     44   // 2 MB max
     45   def imgTooLarge(req: Req) =
     46     req.uploadedFiles.exists(f => f.length > 2097000)
     47 
     48   // 5 MB max
     49   def bgTooLarge(req: Req) =
     50     req.uploadedFiles.exists(f => f.length > 5243000)
     51 
     52   def inValidImg(req: Req): Boolean = req.uploadedFiles.exists(
     53     file => acceptedImages.find(file.mimeType == _).isEmpty)
     54 
     55   def errorCheck(req: Req, imgType: String) = {
     56     if (inValidImg(req))
     57       (false, "Only JPEG, PNG and SVG are allowed.")
     58     else if (imgType == bg.toString && bgTooLarge(req))
     59       (false, "Image is too big. Must be 5MB or smaller.")
     60     else if (imgType == pic.toString && imgTooLarge(req))
     61       (false, "Image is too big. Must be 2MB or smaller.")
     62     else if (imgType.isEmpty)
     63       (false, "Image type is missing")
     64     else
     65       (true, "")
     66   }
     67 
     68   serve("api" / "image" / "upload" prefix {
     69 
     70     case "user" :: Nil Post req =>
     71 
     72       for {
     73         user <- User.currentUser ?~ "Must be logged in" ~> 400
     74         imgType <- S.param("type") ?~ s"Missing image type (${bg.toString} or ${pic.toString})"
     75         file <- Box(req.uploadedFiles) ?~ "File not found"
     76       } yield {
     77         val (valid, err) = errorCheck(req, imgType)
     78         if (valid) {
     79           val fn = StringHelpers.randomString(nameLength)
     80           val res = s3.createFile(fn, file.file, file.mimeType) map {
     81             n =>
     82 
     83               val img = s3.fileUrl(fn)
     84               val id: String =
     85                 if (imgType == bg.toString) {
     86                   deleteFile(user.bgImg.get)
     87                   user.bgImg(fn).update
     88                   imgBgId
     89                 }
     90                 else {
     91                   deleteFile(user.img.get)
     92                   user.img(fn).update
     93                   imgProfileId
     94                 }
     95 
     96               info("Successfully saved: " + file.fileName + " for " + user.name.get)
     97               JavaScriptResponse(Run(
     98                 s"""{"callback":"${UpdateImage(id, img).toJsCmd}"}"""))
     99           }
    100 
    101           Await.result[LiftResponse](res, 1 minute)
    102         }
    103         else {
    104           error(err)
    105           ResponseWithReason(BadResponse(), err)
    106         }
    107       }
    108 
    109     case "blog" :: id :: Nil Post req =>
    110 
    111       for {
    112         blog <- Blog.findByStringId(id) ?~ "Blog does not exist" ~> 400
    113         user <- User.currentUser ?~ "Must be logged in"
    114         imgType <- S.param("type") ?~ s"Missing image type (${bg.toString} or ${pic.toString})"
    115         file <- Box(req.uploadedFiles) ?~ "File not found"
    116       } yield {
    117         val (valid, err) = errorCheck(req, imgType)
    118         if (valid) {
    119           val fn = StringHelpers.randomString(nameLength)
    120           val res = s3.createFile(fn, file.file, file.mimeType) map {
    121             n =>
    122 
    123               val img = s3.fileUrl(fn)
    124               val id: String =
    125                 if (imgType == bg.toString) {
    126                   deleteFile(blog.bgImg.get)
    127                   blog.bgImg(fn).update
    128                   imgBgId
    129                 }
    130                 else {
    131                   deleteFile(blog.img.get)
    132                   blog.img(fn).update
    133                   imgProfileId
    134                 }
    135 
    136               info("Successfully saved: " + file.fileName + " for " + user.name.get)
    137               JavaScriptResponse(Run(
    138                 s"""{"callback":"${UpdateImage(id, img).toJsCmd}"}"""))
    139           }
    140 
    141           info("Successfully saved: " + file.fileName + " for " + blog.name.get)
    142           Await.result[LiftResponse](res, 1 minute)
    143         }
    144         else {
    145           error(err)
    146           ResponseWithReason(BadResponse(), err)
    147         } 
    148       }
    149   })
    150 }