Skip to content

Commit

Permalink
Merge pull request #9 from samuraikun/data_modeling_between_users_and…
Browse files Browse the repository at this point in the history
…_videos

Users と Videos のDB設計を変更
  • Loading branch information
samuraikun authored Oct 2, 2018
2 parents a385289 + 88a4b72 commit 6d41393
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 12 deletions.
26 changes: 24 additions & 2 deletions firestore.rules
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
service cloud.firestore {
match /databases/{database}/documents {
function isAuthenticated() {
return request.auth.uid != null;
}

function isUserAuthenticated(userId) {
return request.auth.uid == userId;
}

function isAdmin() {
return exists(/databases/$(database)/documents/admins/$(request.auth.uid));
}

match /users/{userId} {
allow get: if isAuthenticated();
allow create, update, delete: if isUserAuthenticated(userId) || isAdmin();

match /videos/{videoId} {
allow read: if isAuthenticated();
allow create, update, delete: if isUserAuthenticated(userId) || isAdmin();
}
}

match /videos/{video} {
allow read, write: if request.auth.uid != null;
allow read: if isAuthenticated();
}
}
}
}
30 changes: 30 additions & 0 deletions functions/copyVideoMetadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const functions = require('firebase-functions');
const serviceAccount = require('./config/service_account.json');
const admin = require('firebase-admin');
try {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://fir-reacty-videos.firebaseio.com"
});
admin.firestore().settings({timestampsInSnapshots: true});
} catch (error) {
console.log(error);
}
const firestore = admin.firestore();

exports.onUsersVideoCreate = functions.firestore.document('users/{userId}/videos/{videoId}').onCreate(async (snapshot, context) => {
await copyToRootWithUsersVideoSnapshot(snapshot, context);
});

exports.onUsersVideoUpdate = functions.firestore.document('users/{userId}/videos/{videoId}').onUpdate(async (change, context) => {
await copyToRootWithUsersVideoSnapshot(change.after, context);
});

async function copyToRootWithUsersVideoSnapshot(snapshot, context) {
const userId = context.params.userId;
const videoId = context.params.videoId;
const video = snapshot.data();
video.userRef = firestore.collection('users').doc(userId);

await firestore.collection('videos').doc(videoId).set(video, { merge: true });
}
16 changes: 15 additions & 1 deletion functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,18 @@ if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'transcodeVideo'
*/
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'saveUser') {
exports.saveUser = require('./saveUser').saveUser;
}
}

/*
* Triggers when was created new video data, video data is copied Firestore
*/
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'onUsersVideoCreate') {
exports.onUsersVideoCreate = require('./copyVideoMetadata').onUsersVideoCreate;
}

/*
* Triggers when was updated new video data, video data is copied Firestore
*/
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'onUsersVideoUpdate') {
exports.onUsersVideoUpdate = require('./copyVideoMetadata').onUsersVideoUpdate;
}
15 changes: 13 additions & 2 deletions functions/transcodeVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ function promisifyCommand(command) {
});
}

async function saveVideoMetadata(userToken, metadata) {
const decodedToken = await admin.auth().verifyIdToken(userToken);
const user_id = decodedToken.uid;
const videoRef = admin.firestore().doc(`users/${user_id}`).collection('videos').doc();
metadata = Object.assign(metadata, { uid: videoRef.id });

await videoRef.set(metadata, { merge: true });
}

exports.transcodeVideo = functions.storage.object().onFinalize(async object => {
try {
if (!object.contentType.includes('video') || object.contentType.endsWith('mp4')) {
Expand Down Expand Up @@ -66,11 +75,13 @@ exports.transcodeVideo = functions.storage.object().onFinalize(async object => {
}
});

let metadata = await videoFile.getMetadata();
let transcodedVideoFile = await bucket.file(targetStorageFilePath);
let metadata = await transcodedVideoFile.getMetadata();
const downloadURL = `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(targetTranscodedFilePath)}?alt=media&token=${token}`;
metadata = Object.assign(metadata[0], {downloadURL: downloadURL});
const userToken = object.metadata.idToken;

await admin.firestore().collection('videos').add(metadata);
await saveVideoMetadata(userToken, metadata);

fs.unlinkSync(tempFilePath);
fs.unlinkSync(targetTempFilePath);
Expand Down
23 changes: 16 additions & 7 deletions src/components/VideoUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,22 @@ class Upload extends Component {
try {
const filePath = `videos/${firebase.auth().currentUser.uid}/${video.name}`;
const videoStorageRef = firebase.storage().ref(filePath);
const fileSnapshot = await videoStorageRef.put(video);
const idToken = await firebase.auth().currentUser.getIdToken(true);
const metadataForStorage = {
customMetadata: {
idToken: idToken
}
}
const fileSnapshot = await videoStorageRef.put(video, metadataForStorage);

// mp4以外の動画は、Cloud Functions上で、トランスコードした後に
// メタデータを Firestore に保存する
if (video.type === 'video/mp4') {
const downloadURL = await videoStorageRef.getDownloadURL();
let metadata = _.omitBy(fileSnapshot.metadata, _.isEmpty);
metadata = Object.assign(metadata, {downloadURL: downloadURL});
let metadataForFirestore = _.omitBy(fileSnapshot.metadata, _.isEmpty);
metadataForFirestore = Object.assign(metadataForFirestore, {downloadURL: downloadURL});

this.saveVideoMetadata(metadata);
await this.saveVideoMetadata(metadataForFirestore);
}

if (fileSnapshot.state === 'success') {
Expand All @@ -58,9 +64,12 @@ class Upload extends Component {
}
}

saveVideoMetadata(metadata) {
const collection = firebase.firestore().collection('videos');
return collection.add(metadata);
async saveVideoMetadata(metadata) {
const user_id = firebase.auth().currentUser.uid;
const videoRef = firebase.firestore().doc(`users/${user_id}`).collection('videos').doc();
metadata = Object.assign(metadata, { uid: videoRef.id });

await videoRef.set(metadata, { merge: true });
}

render() {
Expand Down

0 comments on commit 6d41393

Please sign in to comment.