MaazAli/phanime

View on GitHub
collections/libraryEntries.js

Summary

Maintainability
B
6 hrs
Test Coverage
LibraryEntries = new Meteor.Collection("libraryEntries");

LibraryEntriesSchema = new SimpleSchema({
    userId: {
        type: String,
        custom: function() {
            // Check that a user from this ID actually exists
            if (!Meteor.users.findOne({_id: this.value})) {
                return "No user found with this userId";
            }
        },
        index: 1,
        denyUpdate: true
    },
    animeId: {
        type: String,
        custom: function() {
            // Check that an anime from this ID actually exists
            if (!Anime.findOne({_id: this.value})) {
                return "No anime found with this animeId";
            }
        },
        denyUpdate: true
    },
    // This will correspond to an anime title or a manga title
    canonicalTitle: {
        type: String
    },
    type: {
        type: String,
        allowedValues: ['anime', 'manga']
    },
    status: {
        type: String,
        allowedValues: ['Watching', 'Completed', 'Plan to watch', 'On hold', 'Dropped']
    },
    comments: {
        type: String,
        min: 1,
        max: 140,
        optional: true
    },
    rating: {
        type: Number,
        decimal: false,
        min: 1,
        max: 10,
        optional: true
    },
    episodesSeen: {
        type: Number,
        decimal: false,
        min: 1,
        optional: true,
        custom: function() {
            // this is how we're defining the max value
            // We'll need to do this in a roundabout way for now
            // since we can't get a field's value if it wasn't updated
            // together with episodesSeen
            
            // check if the object being validated even has 
            // episodesSeen set
            if (!this.isSet) {
                // it's not set, we shouldn't return any errors
                // this field is optional
                return true;
            }

            if (this.isUpdate) {
                var libraryEntry = LibraryEntries.findOne({_id: this.docId});
                var anime = Anime.findOne({_id: libraryEntry.animeId});
            } else {
                var anime = Anime.findOne({_id: this.field("animeId").value});
            }

            if (anime && anime.totalEpisodes && anime.totalEpisodes > 1) {
                
                if (this.value <= anime.totalEpisodes)
                    return true;
                else 
                    return "Episodes seen value exceeds total episodes";
            } else {
                // if we can't find the total episodes of the anime 
                // we'll just return true for verification 
                return true;
            }
        },
    },
    favourite: {
        type: Boolean,
        optional: true
    },
    privacy: {
        type: Boolean,
        optional: true
    },
    highPriority: {
        type: Boolean,
        optional: true
    },
    rewatching: {
        type: Boolean,
        optional: true
    },
    createdAt: {
        type: Date,
        autoValue: function() {
            if (this.isInsert) {
                return new Date();
            } else if (this.isUpsert) {
                return {$setOnInsert: new Date()};
            } else {
                this.unset();
            }
        },
        denyUpdate: true,
        optional: true // this is only made optional because validation before insert will not work if it was required, however, this does not make much of a difference as the createdAt value will still be generated on insert.
    },
    updatedAt: {
        type: Date,
        autoValue: function() {
            if (this.isUpdate) {
                return new Date();
            }
        },
        denyInsert: true,
        optional: true
    }
});

LibraryEntries.attachSchema(LibraryEntriesSchema);

LibraryEntries.helpers({
    anime: function() {
        return Anime.findOne({_id: this.animeId});
    }
});

LibraryEntries.generalHelpers = {
    uniqueEntry: function(libraryEntry) {
        if (LibraryEntries.findOne({userId: libraryEntry.userId, animeId: libraryEntry.animeId})) {
            return false;
        } else {
            return true;
        }
    }
};


LibraryEntries.allow({

    insert: function(userId, libraryEntry) {
        // the user must be logged in, and the library entry must be created by the user
        // Additionally the library entry must pass validation
        // We'll do a unique check in insert function as well
        return LibraryEntries.generalHelpers.uniqueEntry(libraryEntry) && (userId && libraryEntry.userId === userId);
    },
    update: function(userId, libraryEntry, fields, modifier) {

        // can only change your own library entries


        return (libraryEntry.userId === userId);

    },
    remove: function(userId, doc) {

        // can only remove entries that you own
        return doc.userId === userId;

    }
});