user.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* eslint no-param-reassign: 0 */
  2. import auth from "../../api/auth";
  3. import io from "../../io";
  4. import validation from "../../validation";
  5. const state = {};
  6. const getters = {};
  7. const actions = {};
  8. const mutations = {};
  9. const modules = {
  10. auth: {
  11. namespaced: true,
  12. state: {
  13. userIdMap: {},
  14. userIdRequested: {},
  15. pendingUserIdCallbacks: {},
  16. loggedIn: false,
  17. role: "",
  18. username: "",
  19. userId: "",
  20. banned: false,
  21. ban: {},
  22. gotData: false
  23. },
  24. actions: {
  25. /* eslint-disable-next-line no-unused-vars */
  26. register: ({ commit }, user) => {
  27. return new Promise((resolve, reject) => {
  28. const { username, email, password } = user;
  29. if (!email || !username || !password)
  30. return reject(new Error("Please fill in all fields"));
  31. if (!validation.isLength(email, 3, 254))
  32. return reject(
  33. new Error(
  34. "Email must have between 3 and 254 characters."
  35. )
  36. );
  37. if (
  38. email.indexOf("@") !== email.lastIndexOf("@") ||
  39. !validation.regex.emailSimple.test(email)
  40. )
  41. return reject(new Error("Invalid email format."));
  42. if (!validation.isLength(username, 2, 32))
  43. return reject(
  44. new Error(
  45. "Username must have between 2 and 32 characters."
  46. )
  47. );
  48. if (!validation.regex.azAZ09_.test(username))
  49. return reject(
  50. new Error(
  51. "Invalid username format. Allowed characters: a-z, A-Z, 0-9 and _."
  52. )
  53. );
  54. if (!validation.isLength(password, 6, 200))
  55. return reject(
  56. new Error(
  57. "Password must have between 6 and 200 characters."
  58. )
  59. );
  60. if (!validation.regex.password.test(password))
  61. return reject(
  62. new Error(
  63. "Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character."
  64. )
  65. );
  66. return auth
  67. .register(user)
  68. .then(res => {
  69. return resolve(res);
  70. })
  71. .catch(err => {
  72. return reject(new Error(err.message));
  73. });
  74. });
  75. },
  76. /* eslint-disable-next-line no-unused-vars */
  77. login: ({ commit }, user) => {
  78. return new Promise((resolve, reject) => {
  79. auth.login(user)
  80. .then(() => {
  81. return resolve({
  82. status: "success",
  83. message: "Logged in!"
  84. });
  85. })
  86. .catch(err => {
  87. return reject(new Error(err.message));
  88. });
  89. });
  90. },
  91. logout: () => {
  92. return new Promise((resolve, reject) => {
  93. return auth
  94. .logout()
  95. .then(() => {
  96. return resolve();
  97. })
  98. .catch(() => {
  99. return reject();
  100. });
  101. });
  102. },
  103. getUsernameFromId: ({ commit, state }, userId) => {
  104. return new Promise(resolve => {
  105. if (typeof state.userIdMap[`Z${userId}`] !== "string") {
  106. if (state.userIdRequested[`Z${userId}`] !== true) {
  107. commit("requestingUserId", userId);
  108. io.getSocket(socket => {
  109. socket.emit(
  110. "users.getUsernameFromId",
  111. userId,
  112. res => {
  113. if (res.status === "success") {
  114. commit("mapUserId", {
  115. userId,
  116. username: res.data
  117. });
  118. state.pendingUserIdCallbacks[
  119. `Z${userId}`
  120. ].forEach(cb => cb(res.data));
  121. commit(
  122. "clearPendingCallbacks",
  123. userId
  124. );
  125. return resolve(res.data);
  126. }
  127. return resolve();
  128. }
  129. );
  130. });
  131. } else {
  132. commit("pendingUsername", {
  133. userId,
  134. callback: username => {
  135. return resolve(username);
  136. }
  137. });
  138. }
  139. } else {
  140. resolve(state.userIdMap[`Z${userId}`]);
  141. }
  142. });
  143. },
  144. authData: ({ commit }, data) => {
  145. commit("authData", data);
  146. },
  147. banUser: ({ commit }, ban) => {
  148. commit("banUser", ban);
  149. },
  150. updateUsername: ({ commit }, username) => {
  151. commit("updateUsername", username);
  152. }
  153. },
  154. mutations: {
  155. mapUserId(state, data) {
  156. state.userIdMap[`Z${data.userId}`] = data.username;
  157. state.userIdRequested[`Z${data.userId}`] = false;
  158. },
  159. requestingUserId(state, userId) {
  160. state.userIdRequested[`Z${userId}`] = true;
  161. if (!state.pendingUserIdCallbacks[`Z${userId}`])
  162. state.pendingUserIdCallbacks[`Z${userId}`] = [];
  163. },
  164. pendingUsername(state, data) {
  165. state.pendingUserIdCallbacks[`Z${data.userId}`].push(
  166. data.callback
  167. );
  168. },
  169. clearPendingCallbacks(state, userId) {
  170. state.pendingUserIdCallbacks[`Z${userId}`] = [];
  171. },
  172. authData(state, data) {
  173. state.loggedIn = data.loggedIn;
  174. state.role = data.role;
  175. state.username = data.username;
  176. state.userId = data.userId;
  177. state.gotData = true;
  178. },
  179. banUser(state, ban) {
  180. state.banned = true;
  181. state.ban = ban;
  182. },
  183. updateUsername(state, username) {
  184. state.username = username;
  185. }
  186. }
  187. },
  188. activities: {
  189. namespaced: true,
  190. state: {
  191. activities: [],
  192. position: 0,
  193. maxPosition: 1,
  194. offsettedFromNextSet: 0
  195. },
  196. actions: {
  197. addSetOfActivities: ({ commit }, data) =>
  198. commit("addSetOfActivities", data),
  199. addActivity: ({ commit }, activity) =>
  200. commit("addActivity", activity),
  201. removeActivity: ({ commit }, activityId) =>
  202. commit("removeActivity", activityId),
  203. removeAllActivities: ({ commit }) => commit("removeAllActivities")
  204. },
  205. mutations: {
  206. addActivity(state, activity) {
  207. state.activities.unshift(activity);
  208. state.offsettedFromNextSet += 1;
  209. },
  210. addSetOfActivities(state, data) {
  211. const { activities, set } = data;
  212. if (set > state.position && set <= state.maxPosition) {
  213. state.activities.push(...activities);
  214. state.position = set;
  215. }
  216. },
  217. removeActivity(state, activityId) {
  218. state.activities = state.activities.filter(
  219. activity => activity._id !== activityId
  220. );
  221. },
  222. removeAllActivities(state) {
  223. state.activities = [];
  224. state.position = 0;
  225. state.maxPosition = 1;
  226. state.offsettedFromNextSet = 0;
  227. }
  228. }
  229. },
  230. playlists: {
  231. namespaced: true,
  232. state: {
  233. editing: "",
  234. playlists: []
  235. },
  236. actions: {
  237. editPlaylist: ({ commit }, id) => commit("editPlaylist", id),
  238. setPlaylists: ({ commit }, playlists) =>
  239. commit("setPlaylists", playlists)
  240. },
  241. mutations: {
  242. editPlaylist(state, id) {
  243. state.editing = id;
  244. },
  245. setPlaylists(state, playlists) {
  246. state.playlists = playlists;
  247. }
  248. }
  249. },
  250. preferences: {
  251. namespaced: true,
  252. state: {
  253. nightmode: false,
  254. autoSkipDisliked: true,
  255. activityLogPublic: false
  256. },
  257. actions: {
  258. changeNightmode: ({ commit }, nightmode) => {
  259. commit("changeNightmode", nightmode);
  260. },
  261. changeAutoSkipDisliked: ({ commit }, autoSkipDisliked) => {
  262. commit("changeAutoSkipDisliked", autoSkipDisliked);
  263. },
  264. changeActivityLogPublic: ({ commit }, activityLogPublic) => {
  265. commit("changeActivityLogPublic", activityLogPublic);
  266. }
  267. },
  268. mutations: {
  269. changeNightmode(state, nightmode) {
  270. state.nightmode = nightmode;
  271. },
  272. changeAutoSkipDisliked(state, autoSkipDisliked) {
  273. state.autoSkipDisliked = autoSkipDisliked;
  274. },
  275. changeActivityLogPublic(state, activityLogPublic) {
  276. state.activityLogPublic = activityLogPublic;
  277. }
  278. }
  279. }
  280. };
  281. export default {
  282. namespaced: true,
  283. state,
  284. getters,
  285. actions,
  286. mutations,
  287. modules
  288. };