db.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. const Umzug = require('umzug');
  2. function sequel_log(a,b,c) {
  3. console.log(a);
  4. }
  5. const Sequelize = require('sequelize');
  6. const sequelize = new Sequelize('database', 'username', 'password', {
  7. host: 'localhost',
  8. dialect: 'sqlite',
  9. pool: {
  10. max: 5,
  11. min: 0,
  12. acquire: 30000,
  13. idle: 10000
  14. },
  15. // SQLite only
  16. storage: 'database.sqlite',
  17. logging: sequel_log,
  18. // http://docs.sequelizejs.com/manual/tutorial/querying.html#operators
  19. operatorsAliases: false
  20. });
  21. var User;
  22. var Session;
  23. var Space;
  24. var Membership;
  25. var Artifact;
  26. var Message;
  27. var Action;
  28. module.exports = {
  29. User: sequelize.define('user', {
  30. _id: {type: Sequelize.STRING, primaryKey: true},
  31. email: Sequelize.STRING,
  32. password_hash: Sequelize.STRING,
  33. nickname: Sequelize.STRING,
  34. avatar_original_uri: Sequelize.STRING,
  35. avatar_thumb_uri: Sequelize.STRING,
  36. confirmation_token: Sequelize.STRING,
  37. password_reset_token: Sequelize.STRING,
  38. home_folder_id: Sequelize.STRING,
  39. prefs_language: Sequelize.STRING,
  40. prefs_email_notifications: Sequelize.STRING,
  41. prefs_email_digest: Sequelize.STRING,
  42. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  43. updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
  44. }),
  45. Session: sequelize.define('session', {
  46. token: {type: Sequelize.STRING, primaryKey: true},
  47. user_id: Sequelize.STRING,
  48. expires: Sequelize.DATE,
  49. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  50. device: Sequelize.STRING,
  51. ip: Sequelize.STRING
  52. }),
  53. Space: sequelize.define('space', {
  54. _id: {type: Sequelize.STRING, primaryKey: true},
  55. name: {type: Sequelize.STRING, default: "New Space"},
  56. space_type: {type: Sequelize.STRING, defaultValue: "space"},
  57. creator_id: Sequelize.STRING,
  58. parent_space_id: Sequelize.STRING,
  59. access_mode: {type: Sequelize.STRING, default: "private"}, // "public" || "private"
  60. password: Sequelize.STRING,
  61. edit_hash: Sequelize.STRING,
  62. edit_slug: Sequelize.STRING,
  63. editors_locking: Sequelize.BOOLEAN,
  64. thumbnail_uri: Sequelize.STRING,
  65. width: Sequelize.INTEGER,
  66. height: Sequelize.INTEGER,
  67. background_color: Sequelize.STRING,
  68. background_uri: Sequelize.STRING,
  69. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  70. updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  71. thumbnail_url: Sequelize.STRING,
  72. thumbnail_updated_at: {type: Sequelize.DATE}
  73. }),
  74. Membership: sequelize.define('membership', {
  75. _id: {type: Sequelize.STRING, primaryKey: true},
  76. space_id: Sequelize.STRING,
  77. user_id: Sequelize.STRING,
  78. role: Sequelize.STRING,
  79. code: Sequelize.STRING,
  80. state: {type: Sequelize.STRING, defaultValue: "pending"},
  81. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  82. updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
  83. }),
  84. Message: sequelize.define('message', {
  85. _id: {type: Sequelize.STRING, primaryKey: true},
  86. space_id: Sequelize.STRING,
  87. user_id: Sequelize.STRING,
  88. editor_name: Sequelize.STRING,
  89. message: Sequelize.TEXT,
  90. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  91. updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
  92. }),
  93. Artifact: sequelize.define('artifact', {
  94. _id: {type: Sequelize.STRING, primaryKey: true},
  95. space_id: Sequelize.STRING,
  96. user_id: Sequelize.STRING,
  97. mime: Sequelize.STRING,
  98. thumbnail_uri: Sequelize.STRING,
  99. last_update_user_id: Sequelize.STRING,
  100. editor_name: Sequelize.STRING,
  101. last_update_editor_name: Sequelize.STRING,
  102. description: Sequelize.TEXT,
  103. state: {type: Sequelize.STRING, default: "idle"},
  104. //linked_to: Sequelize.STRING,
  105. title: Sequelize.STRING,
  106. tags: Sequelize.TEXT,
  107. search_text: Sequelize.STRING,
  108. link_uri: Sequelize.STRING,
  109. play_from: Sequelize.DECIMAL,
  110. play_to: Sequelize.DECIMAL,
  111. x: {type: Sequelize.DECIMAL, default: 0.0},
  112. y: {type: Sequelize.DECIMAL, default: 0.0},
  113. z: {type: Sequelize.DECIMAL, default: 0.0},
  114. r: {type: Sequelize.DECIMAL, default: 0.0},
  115. w: {type: Sequelize.DECIMAL, default: 100},
  116. h: {type: Sequelize.DECIMAL, default: 100},
  117. //control_points: [{
  118. // dx: Number, dy: Number
  119. //}],
  120. control_points: Sequelize.TEXT,
  121. group: Sequelize.STRING,
  122. locked: {type: Sequelize.BOOLEAN, default: false},
  123. payload_uri: Sequelize.STRING,
  124. payload_thumbnail_web_uri: Sequelize.STRING,
  125. payload_thumbnail_medium_uri: Sequelize.STRING,
  126. payload_thumbnail_big_uri: Sequelize.STRING,
  127. payload_size: Sequelize.INTEGER, // file size in bytes
  128. fill_color: {type: Sequelize.STRING, default: "transparent"},
  129. stroke_color: {type: Sequelize.STRING, default: "#000000"},
  130. text_color: Sequelize.STRING,
  131. stroke: {type: Sequelize.DECIMAL, default: 0.0},
  132. stroke_style: {type: Sequelize.STRING, default: "solid"},
  133. alpha: {type: Sequelize.DECIMAL, default: 1.0},
  134. order: {type: Sequelize.INTEGER, default: 0},
  135. crop_x: Sequelize.INTEGER,
  136. crop_y: Sequelize.INTEGER,
  137. crop_w: Sequelize.INTEGER,
  138. crop_h: Sequelize.INTEGER,
  139. shape: Sequelize.STRING,
  140. shape_svg: Sequelize.STRING,
  141. padding_left: Sequelize.INTEGER,
  142. padding_right: Sequelize.INTEGER,
  143. padding_top: Sequelize.INTEGER,
  144. padding_bottom: Sequelize.INTEGER,
  145. margin_left: Sequelize.INTEGER,
  146. margin_right: Sequelize.INTEGER,
  147. margin_top: Sequelize.INTEGER,
  148. margin_bottom: Sequelize.INTEGER,
  149. border_radius: Sequelize.INTEGER,
  150. align: {type: Sequelize.STRING, default: "left"},
  151. valign: {type: Sequelize.STRING, default: "top"},
  152. brightness: Sequelize.DECIMAL,
  153. contrast: Sequelize.DECIMAL,
  154. saturation: Sequelize.DECIMAL,
  155. blur: Sequelize.DECIMAL,
  156. hue: Sequelize.DECIMAL,
  157. opacity: Sequelize.DECIMAL,
  158. payload_alternatives: Sequelize.TEXT,
  159. /*payload_alternatives: [{
  160. mime: String,
  161. payload_uri: String,
  162. payload_thumbnail_web_uri: String,
  163. payload_thumbnail_medium_uri: String,
  164. payload_thumbnail_big_uri: String,
  165. payload_size: Number
  166. }],*/
  167. created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
  168. updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
  169. }),
  170. init: async function() {
  171. User = this.User;
  172. Session = this.Session;
  173. Space = this.Space;
  174. Artifact = this.Artifact;
  175. Message = this.Message;
  176. Membership = this.Membership;
  177. Space.belongsTo(User, {
  178. foreignKey: {
  179. name: 'creator_id'
  180. },
  181. as: 'creator'
  182. });
  183. Membership.belongsTo(User, {
  184. foreignKey: {
  185. name: 'user_id'
  186. },
  187. as: 'user'
  188. });
  189. Membership.belongsTo(Space, {
  190. foreignKey: {
  191. name: 'space_id'
  192. },
  193. as: 'space'
  194. });
  195. Artifact.belongsTo(User, {
  196. foreignKey: {
  197. name: 'user_id'
  198. },
  199. as: 'user'
  200. });
  201. Artifact.belongsTo(Space, {
  202. foreignKey: {
  203. name: 'space_id'
  204. },
  205. as: 'space'
  206. });
  207. Message.belongsTo(User, {
  208. foreignKey: {
  209. name: 'user_id'
  210. },
  211. as: 'user'
  212. });
  213. Message.belongsTo(Space, {
  214. foreignKey: {
  215. name: 'space_id'
  216. },
  217. as: 'space'
  218. });
  219. await sequelize.sync();
  220. var umzug = new Umzug({
  221. storage: 'sequelize',
  222. storageOptions: {
  223. sequelize: sequelize
  224. },
  225. migrations: {
  226. params: [
  227. sequelize.getQueryInterface(),
  228. Sequelize
  229. ],
  230. path: './models/migrations',
  231. pattern: /\.js$/
  232. }
  233. });
  234. umzug.up().then(function(migrations) {
  235. console.log('Migration complete up!');
  236. });
  237. },
  238. getUserRoleInSpace: (originalSpace, user, cb) => {
  239. originalSpace.path = [];
  240. console.log("getUserRoleInSpace",originalSpace._id,user._id,user.home_folder_id);
  241. if (originalSpace._id == user.home_folder_id || (originalSpace.creator_id && originalSpace.creator_id == user._id)) {
  242. cb("admin");
  243. } else {
  244. var findMembershipsForSpace = function(space, allMemberships, prevRole) {
  245. Membership.findAll({ where: {
  246. "space": space._id
  247. }}).then(function(parentMemberships) {
  248. var currentMemberships = parentMemberships.concat(allMemberships);
  249. if (space.parent_space_id) {
  250. Space.findOne({ where: {
  251. "_id": space.parent_space_id
  252. }}, function(err, parentSpace) {
  253. findMembershipsForSpace(parentSpace, currentMemberships, prevRole);
  254. });
  255. } else {
  256. // reached the top
  257. var role = prevRole;
  258. space.memberships = currentMemberships;
  259. if (role == "none") {
  260. if (originalSpace.access_mode == "public") {
  261. role = "viewer";
  262. }
  263. }
  264. currentMemberships.forEach(function(m, i) {
  265. if (m.user_id && m.user_id == user._id) {
  266. role = m.role;
  267. }
  268. });
  269. cb(role);
  270. }
  271. });
  272. };
  273. findMembershipsForSpace(originalSpace, [], "none");
  274. }
  275. },
  276. spaceToObject: (space) => {
  277. // FIXME TODO
  278. return space;
  279. },
  280. findUserBySessionToken: (token, cb) => {
  281. Session.findOne({where: {token: token}})
  282. .then(session => {
  283. if (!session) cb(null, null)
  284. else User.findOne({where: {_id: session.user_id}})
  285. .then(user => {
  286. cb(null, user)
  287. })
  288. })
  289. },
  290. unpackArtifact: (a) => {
  291. if (a.tags && (typeof a.tags)=="string") {
  292. a.tags = JSON.parse(a.tags);
  293. }
  294. if (a.control_points && (typeof a.control_points)=="string") {
  295. a.control_points = JSON.parse(a.control_points);
  296. }
  297. if (a.payload_alternatives && (typeof a.payload_alternatives)=="string") {
  298. a.payload_alternatives = JSON.parse(a.payload_alternatives);
  299. }
  300. return a;
  301. },
  302. packArtifact: (a) => {
  303. if (a.tags && (typeof a.tags)!="string") {
  304. a.tags = JSON.stringify(a.tags);
  305. }
  306. if (a.control_points && (typeof a.control_points)!="string") {
  307. a.control_points = JSON.stringify(a.control_points);
  308. }
  309. if (a.payload_alternatives && (typeof a.payload_alternatives)!="string") {
  310. a.payload_alternatives = JSON.stringify(a.payload_alternatives);
  311. }
  312. return a;
  313. }
  314. }