2018-07-17 12:16:24 +02:00
|
|
|
const Umzug = require('umzug');
|
2018-04-12 18:40:58 +02:00
|
|
|
|
|
|
|
function sequel_log(a,b,c) {
|
|
|
|
console.log(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Sequelize = require('sequelize');
|
|
|
|
const sequelize = new Sequelize('database', 'username', 'password', {
|
|
|
|
host: 'localhost',
|
|
|
|
dialect: 'sqlite',
|
|
|
|
|
|
|
|
pool: {
|
|
|
|
max: 5,
|
|
|
|
min: 0,
|
|
|
|
acquire: 30000,
|
|
|
|
idle: 10000
|
|
|
|
},
|
|
|
|
|
|
|
|
// SQLite only
|
|
|
|
storage: 'database.sqlite',
|
|
|
|
logging: sequel_log,
|
|
|
|
|
|
|
|
// http://docs.sequelizejs.com/manual/tutorial/querying.html#operators
|
|
|
|
operatorsAliases: false
|
|
|
|
});
|
|
|
|
|
|
|
|
var User;
|
|
|
|
var Session;
|
|
|
|
var Space;
|
|
|
|
var Membership;
|
|
|
|
var Artifact;
|
|
|
|
var Message;
|
|
|
|
var Action;
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
User: sequelize.define('user', {
|
|
|
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
email: Sequelize.STRING,
|
|
|
|
password_hash: Sequelize.STRING,
|
|
|
|
nickname: Sequelize.STRING,
|
|
|
|
avatar_original_uri: Sequelize.STRING,
|
|
|
|
avatar_thumb_uri: Sequelize.STRING,
|
|
|
|
confirmation_token: Sequelize.STRING,
|
|
|
|
password_reset_token: Sequelize.STRING,
|
|
|
|
home_folder_id: Sequelize.STRING,
|
|
|
|
prefs_language: Sequelize.STRING,
|
|
|
|
prefs_email_notifications: Sequelize.STRING,
|
|
|
|
prefs_email_digest: Sequelize.STRING,
|
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
|
|
|
}),
|
|
|
|
|
|
|
|
Session: sequelize.define('session', {
|
|
|
|
token: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
user_id: Sequelize.STRING,
|
|
|
|
expires: Sequelize.DATE,
|
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
device: Sequelize.STRING,
|
|
|
|
ip: Sequelize.STRING
|
|
|
|
}),
|
|
|
|
|
|
|
|
Space: sequelize.define('space', {
|
|
|
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
name: {type: Sequelize.STRING, default: "New Space"},
|
|
|
|
space_type: {type: Sequelize.STRING, defaultValue: "space"},
|
|
|
|
creator_id: Sequelize.STRING,
|
|
|
|
parent_space_id: Sequelize.STRING,
|
|
|
|
|
|
|
|
access_mode: {type: Sequelize.STRING, default: "private"}, // "public" || "private"
|
|
|
|
password: Sequelize.STRING,
|
|
|
|
edit_hash: Sequelize.STRING,
|
|
|
|
edit_slug: Sequelize.STRING,
|
|
|
|
editors_locking: Sequelize.BOOLEAN,
|
|
|
|
|
|
|
|
thumbnail_uri: Sequelize.STRING,
|
|
|
|
|
|
|
|
width: Sequelize.INTEGER,
|
|
|
|
height: Sequelize.INTEGER,
|
|
|
|
background_color: Sequelize.STRING,
|
|
|
|
background_uri: Sequelize.STRING,
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
thumbnail_url: Sequelize.STRING,
|
|
|
|
thumbnail_updated_at: {type: Sequelize.DATE}
|
|
|
|
}),
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Membership: sequelize.define('membership', {
|
|
|
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
space_id: Sequelize.STRING,
|
|
|
|
user_id: Sequelize.STRING,
|
|
|
|
role: Sequelize.STRING,
|
|
|
|
code: Sequelize.STRING,
|
2020-04-09 14:55:18 +02:00
|
|
|
state: {type: Sequelize.STRING, defaultValue: "pending"}, // valid: "pending", "active"
|
2019-05-19 22:42:23 +02:00
|
|
|
email_invited: Sequelize.STRING,
|
2018-04-12 18:40:58 +02:00
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
|
|
|
}),
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Message: sequelize.define('message', {
|
|
|
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
space_id: Sequelize.STRING,
|
|
|
|
user_id: Sequelize.STRING,
|
|
|
|
editor_name: Sequelize.STRING,
|
|
|
|
message: Sequelize.TEXT,
|
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
|
|
|
}),
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Artifact: sequelize.define('artifact', {
|
|
|
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
|
|
|
space_id: Sequelize.STRING,
|
|
|
|
user_id: Sequelize.STRING,
|
|
|
|
|
|
|
|
mime: Sequelize.STRING,
|
|
|
|
thumbnail_uri: Sequelize.STRING,
|
|
|
|
last_update_user_id: Sequelize.STRING,
|
|
|
|
editor_name: Sequelize.STRING,
|
|
|
|
last_update_editor_name: Sequelize.STRING,
|
|
|
|
description: Sequelize.TEXT,
|
|
|
|
state: {type: Sequelize.STRING, default: "idle"},
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
//linked_to: Sequelize.STRING,
|
|
|
|
title: Sequelize.STRING,
|
|
|
|
tags: Sequelize.TEXT,
|
|
|
|
search_text: Sequelize.STRING,
|
|
|
|
link_uri: Sequelize.STRING,
|
|
|
|
play_from: Sequelize.DECIMAL,
|
|
|
|
play_to: Sequelize.DECIMAL,
|
|
|
|
|
|
|
|
x: {type: Sequelize.DECIMAL, default: 0.0},
|
|
|
|
y: {type: Sequelize.DECIMAL, default: 0.0},
|
|
|
|
z: {type: Sequelize.DECIMAL, default: 0.0},
|
|
|
|
r: {type: Sequelize.DECIMAL, default: 0.0},
|
|
|
|
w: {type: Sequelize.DECIMAL, default: 100},
|
|
|
|
h: {type: Sequelize.DECIMAL, default: 100},
|
|
|
|
|
|
|
|
//control_points: [{
|
|
|
|
// dx: Number, dy: Number
|
|
|
|
//}],
|
|
|
|
|
|
|
|
control_points: Sequelize.TEXT,
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
group: Sequelize.STRING,
|
|
|
|
locked: {type: Sequelize.BOOLEAN, default: false},
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
payload_uri: Sequelize.STRING,
|
|
|
|
payload_thumbnail_web_uri: Sequelize.STRING,
|
|
|
|
payload_thumbnail_medium_uri: Sequelize.STRING,
|
|
|
|
payload_thumbnail_big_uri: Sequelize.STRING,
|
|
|
|
payload_size: Sequelize.INTEGER, // file size in bytes
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
fill_color: {type: Sequelize.STRING, default: "transparent"},
|
|
|
|
stroke_color: {type: Sequelize.STRING, default: "#000000"},
|
|
|
|
text_color: Sequelize.STRING,
|
|
|
|
stroke: {type: Sequelize.DECIMAL, default: 0.0},
|
|
|
|
stroke_style: {type: Sequelize.STRING, default: "solid"},
|
|
|
|
alpha: {type: Sequelize.DECIMAL, default: 1.0},
|
|
|
|
order: {type: Sequelize.INTEGER, default: 0},
|
|
|
|
crop_x: Sequelize.INTEGER,
|
|
|
|
crop_y: Sequelize.INTEGER,
|
|
|
|
crop_w: Sequelize.INTEGER,
|
|
|
|
crop_h: Sequelize.INTEGER,
|
|
|
|
shape: Sequelize.STRING,
|
|
|
|
shape_svg: Sequelize.STRING,
|
|
|
|
padding_left: Sequelize.INTEGER,
|
|
|
|
padding_right: Sequelize.INTEGER,
|
|
|
|
padding_top: Sequelize.INTEGER,
|
|
|
|
padding_bottom: Sequelize.INTEGER,
|
|
|
|
margin_left: Sequelize.INTEGER,
|
|
|
|
margin_right: Sequelize.INTEGER,
|
|
|
|
margin_top: Sequelize.INTEGER,
|
|
|
|
margin_bottom: Sequelize.INTEGER,
|
|
|
|
border_radius: Sequelize.INTEGER,
|
|
|
|
align: {type: Sequelize.STRING, default: "left"},
|
|
|
|
valign: {type: Sequelize.STRING, default: "top"},
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
brightness: Sequelize.DECIMAL,
|
|
|
|
contrast: Sequelize.DECIMAL,
|
|
|
|
saturation: Sequelize.DECIMAL,
|
|
|
|
blur: Sequelize.DECIMAL,
|
|
|
|
hue: Sequelize.DECIMAL,
|
|
|
|
opacity: Sequelize.DECIMAL,
|
|
|
|
|
|
|
|
payload_alternatives: Sequelize.TEXT,
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
/*payload_alternatives: [{
|
|
|
|
mime: String,
|
|
|
|
payload_uri: String,
|
|
|
|
payload_thumbnail_web_uri: String,
|
|
|
|
payload_thumbnail_medium_uri: String,
|
|
|
|
payload_thumbnail_big_uri: String,
|
|
|
|
payload_size: Number
|
|
|
|
}],*/
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
|
|
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
|
|
|
}),
|
2018-07-16 12:30:41 +02:00
|
|
|
|
|
|
|
init: async function() {
|
2018-04-12 18:40:58 +02:00
|
|
|
User = this.User;
|
|
|
|
Session = this.Session;
|
|
|
|
Space = this.Space;
|
|
|
|
Artifact = this.Artifact;
|
|
|
|
Message = this.Message;
|
|
|
|
Membership = this.Membership;
|
|
|
|
|
|
|
|
Space.belongsTo(User, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'creator_id'
|
|
|
|
},
|
|
|
|
as: 'creator'
|
|
|
|
});
|
|
|
|
|
|
|
|
Membership.belongsTo(User, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'user_id'
|
|
|
|
},
|
|
|
|
as: 'user'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Membership.belongsTo(Space, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'space_id'
|
|
|
|
},
|
|
|
|
as: 'space'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Artifact.belongsTo(User, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'user_id'
|
|
|
|
},
|
|
|
|
as: 'user'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Artifact.belongsTo(Space, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'space_id'
|
|
|
|
},
|
|
|
|
as: 'space'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Message.belongsTo(User, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'user_id'
|
|
|
|
},
|
|
|
|
as: 'user'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
Message.belongsTo(Space, {
|
|
|
|
foreignKey: {
|
|
|
|
name: 'space_id'
|
|
|
|
},
|
|
|
|
as: 'space'
|
|
|
|
});
|
2018-07-16 12:30:41 +02:00
|
|
|
|
|
|
|
await sequelize.sync();
|
|
|
|
|
|
|
|
var umzug = new Umzug({
|
|
|
|
storage: 'sequelize',
|
|
|
|
storageOptions: {
|
|
|
|
sequelize: sequelize
|
|
|
|
},
|
|
|
|
migrations: {
|
|
|
|
params: [
|
|
|
|
sequelize.getQueryInterface(),
|
|
|
|
Sequelize
|
|
|
|
],
|
|
|
|
path: './models/migrations',
|
|
|
|
pattern: /\.js$/
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
umzug.up().then(function(migrations) {
|
|
|
|
console.log('Migration complete up!');
|
|
|
|
});
|
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
getUserRoleInSpace: (originalSpace, user, cb) => {
|
|
|
|
originalSpace.path = [];
|
2020-04-09 15:02:10 +02:00
|
|
|
|
2018-04-12 18:40:58 +02:00
|
|
|
if (originalSpace._id == user.home_folder_id || (originalSpace.creator_id && originalSpace.creator_id == user._id)) {
|
|
|
|
cb("admin");
|
|
|
|
} else {
|
|
|
|
var findMembershipsForSpace = function(space, allMemberships, prevRole) {
|
|
|
|
Membership.findAll({ where: {
|
|
|
|
"space": space._id
|
|
|
|
}}).then(function(parentMemberships) {
|
|
|
|
var currentMemberships = parentMemberships.concat(allMemberships);
|
|
|
|
|
|
|
|
if (space.parent_space_id) {
|
|
|
|
Space.findOne({ where: {
|
|
|
|
"_id": space.parent_space_id
|
|
|
|
}}, function(err, parentSpace) {
|
|
|
|
findMembershipsForSpace(parentSpace, currentMemberships, prevRole);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// reached the top
|
|
|
|
var role = prevRole;
|
|
|
|
space.memberships = currentMemberships;
|
|
|
|
|
|
|
|
if (role == "none") {
|
|
|
|
if (originalSpace.access_mode == "public") {
|
|
|
|
role = "viewer";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
currentMemberships.forEach(function(m, i) {
|
|
|
|
if (m.user_id && m.user_id == user._id) {
|
|
|
|
role = m.role;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
cb(role);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
findMembershipsForSpace(originalSpace, [], "none");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
spaceToObject: (space) => {
|
|
|
|
// FIXME TODO
|
|
|
|
return space;
|
|
|
|
},
|
|
|
|
|
|
|
|
findUserBySessionToken: (token, cb) => {
|
|
|
|
Session.findOne({where: {token: token}})
|
|
|
|
.then(session => {
|
|
|
|
if (!session) cb(null, null)
|
|
|
|
else User.findOne({where: {_id: session.user_id}})
|
|
|
|
.then(user => {
|
|
|
|
cb(null, user)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
unpackArtifact: (a) => {
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.tags && (typeof a.tags)=="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.tags = JSON.parse(a.tags);
|
|
|
|
}
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.control_points && (typeof a.control_points)=="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.control_points = JSON.parse(a.control_points);
|
|
|
|
}
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.payload_alternatives && (typeof a.payload_alternatives)=="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.payload_alternatives = JSON.parse(a.payload_alternatives);
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
},
|
|
|
|
|
|
|
|
packArtifact: (a) => {
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.tags && (typeof a.tags)!="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.tags = JSON.stringify(a.tags);
|
|
|
|
}
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.control_points && (typeof a.control_points)!="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.control_points = JSON.stringify(a.control_points);
|
|
|
|
}
|
2018-04-15 00:23:52 +02:00
|
|
|
if (a.payload_alternatives && (typeof a.payload_alternatives)!="string") {
|
2018-04-12 18:40:58 +02:00
|
|
|
a.payload_alternatives = JSON.stringify(a.payload_alternatives);
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
}
|