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 }