Update sequelize & DB setup:
- Split models & associations into their own files - Update columns and requirements - Create PermissionLevel model & add to relevant models
This commit is contained in:
parent
86897be78a
commit
071e1e6586
|
@ -102,5 +102,5 @@ fastify.listen(fastify.siteConfig.port, function (err, address) {
|
|||
}
|
||||
|
||||
fastify.decorate('canEmail', typeof fastify.nodemailer !== 'undefined');
|
||||
fastify.decorate('models', require('./sequelize/getModels')(fastify.sequelize));
|
||||
fastify.decorate('models', require('./sequelize/models')(fastify.sequelize));
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
BookReference,
|
||||
Review,
|
||||
} = models;
|
||||
|
||||
BookReference.hasMany(Review);
|
||||
|
||||
return BookReference;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
Recommendation,
|
||||
User,
|
||||
BookReference,
|
||||
} = models;
|
||||
|
||||
Recommendation.belongsTo(User, {
|
||||
foreignKey: 'fromUser',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
Recommendation.belongsTo(User, {
|
||||
foreignKey: 'toUser',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
Recommendation.belongsTo(BookReference, {
|
||||
foreignKey: 'bookId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
return Recommendation;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
Review,
|
||||
User,
|
||||
PermissionLevel,
|
||||
BookReference,
|
||||
} = models;
|
||||
|
||||
Review.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
Review.belongsTo(PermissionLevel, {
|
||||
foreignKey: 'permissionLevel',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
|
||||
Review.belongsTo(BookReference, {
|
||||
foreignKey: 'bookReferenceId',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
|
||||
return Review;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
Shelf,
|
||||
User,
|
||||
ShelfItem,
|
||||
PermissionLevel,
|
||||
} = models;
|
||||
|
||||
Shelf.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
Shelf.belongsTo(PermissionLevel, {
|
||||
foreignKey: 'permissionLevel',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
|
||||
Shelf.belongsTo(User, {
|
||||
foreignKey: 'permissionLevel',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
Shelf.hasMany(ShelfItem);
|
||||
|
||||
return Shelf;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
ShelfItem,
|
||||
Shelf,
|
||||
BookReference,
|
||||
Status,
|
||||
} = models;
|
||||
|
||||
ShelfItem.belongsTo(Shelf, {
|
||||
foreignKey: 'shelfId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
ShelfItem.belongsTo(BookReference, {
|
||||
foreignKey: 'bookId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
ShelfItem.hasMany(Status);
|
||||
|
||||
return ShelfItem;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
Status,
|
||||
User,
|
||||
ShelfItem,
|
||||
} = models;
|
||||
|
||||
Status.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
Status.belongsTo(PermissionLevel, {
|
||||
foreignKey: 'permissionLevel',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
|
||||
Status.belongsTo(ShelfItem, {
|
||||
foreignKey: 'shelfItemId',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
module.exports = models => {
|
||||
const {
|
||||
User,
|
||||
PermissionLevel,
|
||||
Shelf,
|
||||
Status,
|
||||
Review,
|
||||
Recommendation,
|
||||
} = models;
|
||||
|
||||
User.belongsTo(PermissionLevel, {
|
||||
foreignKey: 'permissionLevel',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
User.hasMany(Shelf);
|
||||
User.hasMany(Status);
|
||||
User.hasMany(Review);
|
||||
User.hasMany(Recommendation, {
|
||||
foreignKey: 'toUser',
|
||||
});
|
||||
|
||||
return User;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = models => {
|
||||
const associatedModels = {};
|
||||
|
||||
Object.keys(models).forEach(modelName => {
|
||||
const associationFileName = path.resolve(__dirname, modelName, '.js');
|
||||
if (fs.existsSync(associationFileName)) {
|
||||
associatedModels[modelName] = require(associationFileName)(models);
|
||||
} else {
|
||||
associatedModels[modelName] = models[modelName];
|
||||
}
|
||||
});
|
||||
|
||||
return associatedModels;
|
||||
};
|
|
@ -1,392 +0,0 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
function getModels (sequelize) {
|
||||
const User = sequelize.define('user', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
isEmail: true,
|
||||
len: [5, 150],
|
||||
},
|
||||
},
|
||||
username: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
is: /^[a-z0-9_]+$/i, // Is a set of characters a-z, 0-9, or _, case insensitive
|
||||
len: [2, 32],
|
||||
},
|
||||
},
|
||||
displayName: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
len: [1, 32],
|
||||
},
|
||||
},
|
||||
passwordHash: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
passwordSalt: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
accountConfirm: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
|
||||
const Shelf = sequelize.define('shelf', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
len: [1, 32],
|
||||
},
|
||||
},
|
||||
isPublic: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
isDeletable: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
Shelf.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
User.hasMany(Shelf);
|
||||
|
||||
const BookReference = sequelize.define('bookReference', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
description: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
comment: 'The description is attempted to be made up of the type of work and the author',
|
||||
},
|
||||
sources: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
defaultValue: [],
|
||||
comment: 'A JSON array with each element being an object with named source <STRING> and source id <STRING>',
|
||||
},
|
||||
covers: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
defaultValue: [],
|
||||
comment: 'A JSON array with each element being an object with image url <STRING> and source id <STRING>',
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['name', 'description'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const ShelfItem = sequelize.define('shelfItem', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
shelfId: {
|
||||
type: Sequelize.INTEGER,
|
||||
references: {
|
||||
model: Shelf,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
bookId: {
|
||||
type: Sequelize.INTEGER,
|
||||
references: {
|
||||
model: BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
bookEdition: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
comment: 'An object with properties `source` and `id`',
|
||||
},
|
||||
order: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
Shelf.hasMany(ShelfItem);
|
||||
ShelfItem.belongsTo(Shelf, {
|
||||
foreignKey: 'shelfId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
ShelfItem.belongsTo(BookReference, {
|
||||
foreignKey: 'bookId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
|
||||
const Status = sequelize.define('status', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
},
|
||||
shelfItemId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: ShelfItem,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
progress: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
User.hasMany(Status);
|
||||
Status.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
ShelfItem.hasMany(Status);
|
||||
Status.belongsTo(ShelfItem, {
|
||||
foreignKey: 'shelfItemId',
|
||||
// onDelete: 'IGNORE'
|
||||
});
|
||||
|
||||
const Review = sequelize.define('review', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
},
|
||||
bookReferenceId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
rating: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
User.hasMany(Review);
|
||||
Review.belongsTo(User, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
BookReference.hasMany(Review);
|
||||
Review.belongsTo(BookReference, {
|
||||
foreignKey: 'shelfItemId',
|
||||
// onDelete: 'IGNORE'
|
||||
});
|
||||
|
||||
const Recommendation = sequelize.define('recommendation', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
toUser: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: false,
|
||||
},
|
||||
book: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
data: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
Recommendation.belongsTo(User, {
|
||||
foreignKey: 'fromUser',
|
||||
onDelete: 'SET NULL',
|
||||
});
|
||||
Recommendation.belongsTo(User, {
|
||||
foreignKey: 'toUser',
|
||||
onDelete: 'CASCADE',
|
||||
});
|
||||
User.hasMany(Recommendation, {
|
||||
foreignKey: 'toUser',
|
||||
})
|
||||
|
||||
return {
|
||||
User,
|
||||
Shelf,
|
||||
BookReference,
|
||||
ShelfItem,
|
||||
StatusType,
|
||||
Status,
|
||||
Review,
|
||||
Recommendation,
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = getModels;
|
|
@ -4,6 +4,7 @@ const fs = require('fs');
|
|||
const dbVersion = '0.0.0';
|
||||
|
||||
function migrateDb(oldVersion, sequelize) {
|
||||
const models = sequelize.models;
|
||||
// if (oldVersion < targetVersion) {
|
||||
// migrate db here
|
||||
// }
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('BookReference', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
description: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
comment: 'The description is attempted to be made up of the type of work and the author',
|
||||
},
|
||||
sources: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: false,
|
||||
defaultValue: [],
|
||||
comment: 'A JSON array with each element being an object with named source <STRING> and source id <STRING>',
|
||||
},
|
||||
covers: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: false,
|
||||
defaultValue: [],
|
||||
comment: 'A JSON array with each element being an object with image url <STRING> and source id <STRING>',
|
||||
},
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['name', 'description'],
|
||||
},
|
||||
{
|
||||
fields: ['name'],
|
||||
},
|
||||
{
|
||||
fields: ['description'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('PermissionLevel', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: false,
|
||||
comment: 'Represents the level number with 100 being the private and 0 being public',
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
unique: true,
|
||||
allowNull: false,
|
||||
},
|
||||
description: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
}, {
|
||||
timestamps: false,
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('Recommendation', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
fromUser: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: sequelize.models.User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
},
|
||||
toUser: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
isNotBlank: value => value.length > 2,
|
||||
}
|
||||
},
|
||||
bookId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
paranoid: true, // If toUser deletes recommendation, keep in database so fromUser can still see that they sent the recommendation.
|
||||
indexes: [
|
||||
{
|
||||
fields: ['toUser'],
|
||||
},
|
||||
{
|
||||
fields: ['fromUser'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,70 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('Review', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
permissionLevel: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.PermissionLevel,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
},
|
||||
bookReferenceId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
bookEdition: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
comment: 'An object with properties `source` <STRING> and `id` <STRING> where `source` is the domain where the edition was taken from `id` is the reference to the edition in source',
|
||||
},
|
||||
rating: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['userId'],
|
||||
},
|
||||
{
|
||||
fields: ['bookReferenceId'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('Shelf', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
len: [1, 32],
|
||||
},
|
||||
},
|
||||
permissionLevel: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.PermissionLevel,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
isDeletable: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['userId'],
|
||||
},
|
||||
{
|
||||
fields: ['permissionLevel'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('ShelfItem', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
shelfId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.Shelf,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
bookId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.BookReference,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
}
|
||||
},
|
||||
bookEdition: {
|
||||
type: Sequelize.JSON,
|
||||
allowNull: true,
|
||||
comment: 'An object with properties `source` <STRING> and `id` <STRING> where `source` is the domain where the edition was taken from `id` is the reference to the edition in source',
|
||||
},
|
||||
order: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['shelfId'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('Status', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.User,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
},
|
||||
permissionLevel: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.PermissionLevel,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
comment: 'This permission level should be the level of the ShelfItem or lower.',
|
||||
},
|
||||
text: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
},
|
||||
shelfItemId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: sequelize.models.ShelfItem,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
},
|
||||
progress: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
comment: 'A number from 0 to 100 that represents percent completion',
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['userId'],
|
||||
},
|
||||
{
|
||||
fields: ['shelfItemId'],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = sequelize => sequelize.define('User', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
isEmail: true,
|
||||
len: [5, 150],
|
||||
},
|
||||
},
|
||||
username: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
is: /^[a-z0-9_]+$/i, // Is a set of characters a-z, 0-9, or _, case insensitive
|
||||
len: [2, 32],
|
||||
},
|
||||
},
|
||||
displayName: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
len: [1, 32],
|
||||
},
|
||||
},
|
||||
permissionLevel: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: sequelize.models.PermissionLevel,
|
||||
key: 'id',
|
||||
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
|
||||
},
|
||||
comment: 'Enable profile to be viewed only by users of this permission level. "Followers" is interpreted as "Users this user is following" for this case.',
|
||||
},
|
||||
passwordHash: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
passwordSalt: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
accountConfirm: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// Timestamps
|
||||
createdAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
const path = require('path');
|
||||
|
||||
module.exports = sequelize => {
|
||||
const modelNames = [ // This is the order required to correctly get references.
|
||||
'PermissionLevel',
|
||||
'User',
|
||||
'BookReference',
|
||||
'Shelf',
|
||||
'ShelfItem',
|
||||
'Status',
|
||||
'Review',
|
||||
'Recommendation',
|
||||
];
|
||||
|
||||
const models = {};
|
||||
modelNames.forEach(modelName => {
|
||||
const filename = `./${modelName}.js`;
|
||||
models[modelName] = require(path.resolve(__dirname, filename))(sequelize);
|
||||
});
|
||||
|
||||
return require(path.resolve(__dirname, '../associations'))(models);
|
||||
};
|
|
@ -37,6 +37,7 @@ switch (siteConfig.db_engine) {
|
|||
}
|
||||
|
||||
const sequelize = new Sequelize(sequelizeConfig);
|
||||
const models = require('./models')(sequelize);
|
||||
|
||||
const migration = require('./migration');
|
||||
const dbVersionPath = path.resolve(__dirname, './.dbversion');
|
||||
|
@ -45,7 +46,7 @@ if (!force) {
|
|||
const installedDbVersion = fs.readFileSync(dbVersionPath);
|
||||
if (installedDbVersion < migration.dbVersion) {
|
||||
console.log(`Migrating from ${installedDbVersion} to ${migration.dbVersion}...`);
|
||||
migration.migrateDb(installedDbVersion, sequelize);
|
||||
migration.migrateDb(installedDbVersion, sequelize, models);
|
||||
return fs.writeFile(dbVersionPath, migration.dbVersion, err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
|
@ -63,8 +64,34 @@ if (!force) {
|
|||
|
||||
console.log(`Installing database tables${force ? ', dropping existing ones first' : ''}...`);
|
||||
sequelize.sync({ force }).then(() => {
|
||||
console.log(`Tables installed! Creating Permission Levels...`);
|
||||
return models.PermissionLevel.bulkCreate([
|
||||
{
|
||||
id: 100,
|
||||
name: 'db.privacyLevel.private',
|
||||
description: 'db.privacyLevel.privateDescription',
|
||||
},
|
||||
{
|
||||
id: 66,
|
||||
name: 'db.privacyLevel.friends',
|
||||
description: 'db.privacyLevel.friendsDescription',
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
name: 'db.privacyLevel.followers',
|
||||
description: 'db.privacyLevel.followersDescription',
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
name: 'db.privacyLevel.public',
|
||||
description: 'db.privacyLevel.publicDescription',
|
||||
},
|
||||
]).catch((err) => {
|
||||
console.error('Could not create Permission Levels:\n', err);
|
||||
});
|
||||
}).then(() => {
|
||||
sequelize.close();
|
||||
console.log(`Tables installed! Writing database version to ${dbVersionPath}...`);
|
||||
console.log(`Permission Levels created! Writing database version to ${dbVersionPath}...`);
|
||||
fs.writeFile(dbVersionPath, migration.dbVersion, err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
|
|
26
yarn.lock
26
yarn.lock
|
@ -4608,22 +4608,6 @@ node-libs-browser@^2.0.0:
|
|||
util "^0.11.0"
|
||||
vm-browserify "^1.0.1"
|
||||
|
||||
node-pre-gyp@*:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
|
||||
integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.2"
|
||||
mkdirp "^0.5.1"
|
||||
needle "^2.2.1"
|
||||
nopt "^4.0.1"
|
||||
npm-packlist "^1.1.6"
|
||||
npmlog "^4.0.2"
|
||||
rc "^1.2.7"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
tar "^4.4.2"
|
||||
|
||||
node-pre-gyp@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
|
||||
|
@ -5215,10 +5199,10 @@ pg-types@^2.1.0:
|
|||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^7.16.0:
|
||||
version "7.17.0"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-7.17.0.tgz#1fcf82238dcbebea63e192c944345c25c86992fc"
|
||||
integrity sha512-70Q4ZzIdPgwMPb3zUIzAUwigNJ4v5vsWdMED6OzXMfOECeYTvTm7iSC3FpKizu/R1BHL8Do3bLs6ltGfOTAnqg==
|
||||
pg@^7.17.0:
|
||||
version "7.17.1"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-7.17.1.tgz#1eb4d900e1f21f43978b306972b02a2329138755"
|
||||
integrity sha512-SYWEip6eADsgDQIZk0bmB2JDOrC8Xu6z10KlhlXl03NSomwVmHB6ZTVyDCwOfT6bXHI8QndJdk5XxSSRXikaSA==
|
||||
dependencies:
|
||||
buffer-writer "2.0.0"
|
||||
packet-reader "1.0.0"
|
||||
|
@ -6914,7 +6898,7 @@ tar-stream@^2.0.0:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@^4, tar@^4.4.2:
|
||||
tar@^4:
|
||||
version "4.4.13"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
||||
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
|
||||
|
|
Loading…
Reference in New Issue