aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api')
-rw-r--r--server/controllers/api/remote.js95
-rw-r--r--server/controllers/api/videos.js99
2 files changed, 158 insertions, 36 deletions
diff --git a/server/controllers/api/remote.js b/server/controllers/api/remote.js
index a6753a2b0..c7a5658e8 100644
--- a/server/controllers/api/remote.js
+++ b/server/controllers/api/remote.js
@@ -50,28 +50,35 @@ function remoteVideos (req, res, next) {
50 return res.type('json').status(204).end() 50 return res.type('json').status(204).end()
51} 51}
52 52
53function addRemoteVideo (videoToCreateData, fromHost, callback) { 53function addRemoteVideo (videoToCreateData, fromHost, finalCallback) {
54 logger.debug('Adding remote video "%s".', videoToCreateData.name) 54 logger.debug('Adding remote video "%s".', videoToCreateData.name)
55 55
56 waterfall([ 56 waterfall([
57 57
58 function findOrCreatePod (callback) { 58 function startTransaction (callback) {
59 db.sequelize.transaction().asCallback(function (err, t) {
60 return callback(err, t)
61 })
62 },
63
64 function findOrCreatePod (t, callback) {
59 const query = { 65 const query = {
60 where: { 66 where: {
61 host: fromHost 67 host: fromHost
62 }, 68 },
63 defaults: { 69 defaults: {
64 host: fromHost 70 host: fromHost
65 } 71 },
72 transaction: t
66 } 73 }
67 74
68 db.Pod.findOrCreate(query).asCallback(function (err, result) { 75 db.Pod.findOrCreate(query).asCallback(function (err, result) {
69 // [ instance, wasCreated ] 76 // [ instance, wasCreated ]
70 return callback(err, result[0]) 77 return callback(err, t, result[0])
71 }) 78 })
72 }, 79 },
73 80
74 function findOrCreateAuthor (pod, callback) { 81 function findOrCreateAuthor (t, pod, callback) {
75 const username = videoToCreateData.author 82 const username = videoToCreateData.author
76 83
77 const query = { 84 const query = {
@@ -82,16 +89,45 @@ function addRemoteVideo (videoToCreateData, fromHost, callback) {
82 defaults: { 89 defaults: {
83 name: username, 90 name: username,
84 podId: pod.id 91 podId: pod.id
85 } 92 },
93 transaction: t
86 } 94 }
87 95
88 db.Author.findOrCreate(query).asCallback(function (err, result) { 96 db.Author.findOrCreate(query).asCallback(function (err, result) {
89 // [ instance, wasCreated ] 97 // [ instance, wasCreated ]
90 return callback(err, result[0]) 98 return callback(err, t, result[0])
91 }) 99 })
92 }, 100 },
93 101
94 function createVideoObject (author, callback) { 102 function findOrCreateTags (t, author, callback) {
103 const tags = videoToCreateData.tags
104 const tagInstances = []
105
106 each(tags, function (tag, callbackEach) {
107 const query = {
108 where: {
109 name: tag
110 },
111 defaults: {
112 name: tag
113 },
114 transaction: t
115 }
116
117 db.Tag.findOrCreate(query).asCallback(function (err, res) {
118 if (err) return callbackEach(err)
119
120 // res = [ tag, isCreated ]
121 const tag = res[0]
122 tagInstances.push(tag)
123 return callbackEach()
124 })
125 }, function (err) {
126 return callback(err, t, author, tagInstances)
127 })
128 },
129
130 function createVideoObject (t, author, tagInstances, callback) {
95 const videoData = { 131 const videoData = {
96 name: videoToCreateData.name, 132 name: videoToCreateData.name,
97 remoteId: videoToCreateData.remoteId, 133 remoteId: videoToCreateData.remoteId,
@@ -99,31 +135,58 @@ function addRemoteVideo (videoToCreateData, fromHost, callback) {
99 infoHash: videoToCreateData.infoHash, 135 infoHash: videoToCreateData.infoHash,
100 description: videoToCreateData.description, 136 description: videoToCreateData.description,
101 authorId: author.id, 137 authorId: author.id,
102 duration: videoToCreateData.duration, 138 duration: videoToCreateData.duration
103 tags: videoToCreateData.tags
104 } 139 }
105 140
106 const video = db.Video.build(videoData) 141 const video = db.Video.build(videoData)
107 142
108 return callback(null, video) 143 return callback(null, t, tagInstances, video)
109 }, 144 },
110 145
111 function generateThumbnail (video, callback) { 146 function generateThumbnail (t, tagInstances, video, callback) {
112 db.Video.generateThumbnailFromBase64(video, videoToCreateData.thumbnailBase64, function (err) { 147 db.Video.generateThumbnailFromBase64(video, videoToCreateData.thumbnailBase64, function (err) {
113 if (err) { 148 if (err) {
114 logger.error('Cannot generate thumbnail from base 64 data.', { error: err }) 149 logger.error('Cannot generate thumbnail from base 64 data.', { error: err })
115 return callback(err) 150 return callback(err)
116 } 151 }
117 152
118 video.save().asCallback(callback) 153 return callback(err, t, tagInstances, video)
119 }) 154 })
120 }, 155 },
121 156
122 function insertIntoDB (video, callback) { 157 function insertVideoIntoDB (t, tagInstances, video, callback) {
123 video.save().asCallback(callback) 158 const options = {
159 transaction: t
160 }
161
162 video.save(options).asCallback(function (err, videoCreated) {
163 return callback(err, t, tagInstances, videoCreated)
164 })
165 },
166
167 function associateTagsToVideo (t, tagInstances, video, callback) {
168 const options = { transaction: t }
169
170 video.setTags(tagInstances, options).asCallback(function (err) {
171 return callback(err, t)
172 })
124 } 173 }
125 174
126 ], callback) 175 ], function (err, t) {
176 if (err) {
177 logger.error('Cannot insert the remote video.')
178
179 // Abort transaction?
180 if (t) t.rollback()
181
182 return finalCallback(err)
183 }
184
185 // Commit transaction
186 t.commit()
187
188 return finalCallback()
189 })
127} 190}
128 191
129function removeRemoteVideo (videoToRemoveData, fromHost, callback) { 192function removeRemoteVideo (videoToRemoveData, fromHost, callback) {
diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos.js
index a61f2b2c9..992f03db0 100644
--- a/server/controllers/api/videos.js
+++ b/server/controllers/api/videos.js
@@ -1,5 +1,6 @@
1'use strict' 1'use strict'
2 2
3const each = require('async/each')
3const express = require('express') 4const express = require('express')
4const fs = require('fs') 5const fs = require('fs')
5const multer = require('multer') 6const multer = require('multer')
@@ -87,7 +88,13 @@ function addVideo (req, res, next) {
87 88
88 waterfall([ 89 waterfall([
89 90
90 function findOrCreateAuthor (callback) { 91 function startTransaction (callback) {
92 db.sequelize.transaction().asCallback(function (err, t) {
93 return callback(err, t)
94 })
95 },
96
97 function findOrCreateAuthor (t, callback) {
91 const username = res.locals.oauth.token.user.username 98 const username = res.locals.oauth.token.user.username
92 99
93 const query = { 100 const query = {
@@ -98,75 +105,125 @@ function addVideo (req, res, next) {
98 defaults: { 105 defaults: {
99 name: username, 106 name: username,
100 podId: null // null because it is OUR pod 107 podId: null // null because it is OUR pod
101 } 108 },
109 transaction: t
102 } 110 }
103 111
104 db.Author.findOrCreate(query).asCallback(function (err, result) { 112 db.Author.findOrCreate(query).asCallback(function (err, result) {
105 // [ instance, wasCreated ] 113 // [ instance, wasCreated ]
106 return callback(err, result[0]) 114 return callback(err, t, result[0])
115 })
116 },
117
118 function findOrCreateTags (t, author, callback) {
119 const tags = videoInfos.tags
120 const tagInstances = []
121
122 each(tags, function (tag, callbackEach) {
123 const query = {
124 where: {
125 name: tag
126 },
127 defaults: {
128 name: tag
129 },
130 transaction: t
131 }
132
133 db.Tag.findOrCreate(query).asCallback(function (err, res) {
134 if (err) return callbackEach(err)
135
136 // res = [ tag, isCreated ]
137 const tag = res[0]
138 tagInstances.push(tag)
139 return callbackEach()
140 })
141 }, function (err) {
142 return callback(err, t, author, tagInstances)
107 }) 143 })
108 }, 144 },
109 145
110 function createVideoObject (author, callback) { 146 function createVideoObject (t, author, tagInstances, callback) {
111 const videoData = { 147 const videoData = {
112 name: videoInfos.name, 148 name: videoInfos.name,
113 remoteId: null, 149 remoteId: null,
114 extname: path.extname(videoFile.filename), 150 extname: path.extname(videoFile.filename),
115 description: videoInfos.description, 151 description: videoInfos.description,
116 duration: videoFile.duration, 152 duration: videoFile.duration,
117 tags: videoInfos.tags,
118 authorId: author.id 153 authorId: author.id
119 } 154 }
120 155
121 const video = db.Video.build(videoData) 156 const video = db.Video.build(videoData)
122 157
123 return callback(null, author, video) 158 return callback(null, t, author, tagInstances, video)
124 }, 159 },
125 160
126 // Set the videoname the same as the id 161 // Set the videoname the same as the id
127 function renameVideoFile (author, video, callback) { 162 function renameVideoFile (t, author, tagInstances, video, callback) {
128 const videoDir = constants.CONFIG.STORAGE.VIDEOS_DIR 163 const videoDir = constants.CONFIG.STORAGE.VIDEOS_DIR
129 const source = path.join(videoDir, videoFile.filename) 164 const source = path.join(videoDir, videoFile.filename)
130 const destination = path.join(videoDir, video.getVideoFilename()) 165 const destination = path.join(videoDir, video.getVideoFilename())
131 166
132 fs.rename(source, destination, function (err) { 167 fs.rename(source, destination, function (err) {
133 return callback(err, author, video) 168 return callback(err, t, author, tagInstances, video)
134 }) 169 })
135 }, 170 },
136 171
137 function insertIntoDB (author, video, callback) { 172 function insertVideoIntoDB (t, author, tagInstances, video, callback) {
138 video.save().asCallback(function (err, videoCreated) { 173 const options = { transaction: t }
174
175 // Add tags association
176 video.save(options).asCallback(function (err, videoCreated) {
177 if (err) return callback(err)
178
139 // Do not forget to add Author informations to the created video 179 // Do not forget to add Author informations to the created video
140 videoCreated.Author = author 180 videoCreated.Author = author
141 181
142 return callback(err, videoCreated) 182 return callback(err, t, tagInstances, videoCreated)
143 }) 183 })
144 }, 184 },
145 185
146 function sendToFriends (video, callback) { 186 function associateTagsToVideo (t, tagInstances, video, callback) {
187 const options = { transaction: t }
188
189 video.setTags(tagInstances, options).asCallback(function (err) {
190 video.Tags = tagInstances
191
192 return callback(err, t, video)
193 })
194 },
195
196 function sendToFriends (t, video, callback) {
147 video.toRemoteJSON(function (err, remoteVideo) { 197 video.toRemoteJSON(function (err, remoteVideo) {
148 if (err) return callback(err) 198 if (err) return callback(err)
149 199
150 // Now we'll add the video's meta data to our friends 200 // Now we'll add the video's meta data to our friends
151 friends.addVideoToFriends(remoteVideo) 201 friends.addVideoToFriends(remoteVideo)
152 202
153 return callback(null) 203 return callback(null, t)
154 }) 204 })
155 } 205 }
156 206
157 ], function andFinally (err) { 207 ], function andFinally (err, t) {
158 if (err) { 208 if (err) {
159 logger.error('Cannot insert the video.') 209 logger.error('Cannot insert the video.')
210
211 // Abort transaction?
212 if (t) t.rollback()
213
160 return next(err) 214 return next(err)
161 } 215 }
162 216
217 // Commit transaction
218 t.commit()
219
163 // TODO : include Location of the new video -> 201 220 // TODO : include Location of the new video -> 201
164 return res.type('json').status(204).end() 221 return res.type('json').status(204).end()
165 }) 222 })
166} 223}
167 224
168function getVideo (req, res, next) { 225function getVideo (req, res, next) {
169 db.Video.loadAndPopulateAuthorAndPod(req.params.id, function (err, video) { 226 db.Video.loadAndPopulateAuthorAndPodAndTags(req.params.id, function (err, video) {
170 if (err) return next(err) 227 if (err) return next(err)
171 228
172 if (!video) { 229 if (!video) {
@@ -222,12 +279,14 @@ function removeVideo (req, res, next) {
222} 279}
223 280
224function searchVideos (req, res, next) { 281function searchVideos (req, res, next) {
225 db.Video.searchAndPopulateAuthorAndPod(req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort, 282 db.Video.searchAndPopulateAuthorAndPodAndTags(
226 function (err, videosList, videosTotal) { 283 req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
227 if (err) return next(err) 284 function (err, videosList, videosTotal) {
285 if (err) return next(err)
228 286
229 res.json(getFormatedVideos(videosList, videosTotal)) 287 res.json(getFormatedVideos(videosList, videosTotal))
230 }) 288 }
289 )
231} 290}
232 291
233// --------------------------------------------------------------------------- 292// ---------------------------------------------------------------------------