| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 | import async from "async";import config from "config";// eslint-disable-next-lineimport moduleManager from "../../index";const permissions = {};permissions.dj = {	"stations.autofill": true,	"stations.blacklist": true,	"stations.index": true,	"stations.playback.toggle": true,	"stations.queue.remove": true,	"stations.queue.reposition": true,	"stations.queue.reset": true,	"stations.request": true,	"stations.skip": true,	"stations.view": true,	"stations.view.manage": true};permissions.owner = {	...permissions.dj,	"stations.djs.add": true,	"stations.djs.remove": true,	"stations.remove": true,	"stations.update": true};permissions.moderator = {	...permissions.owner,	"admin.view": true,	"admin.view.import": true,	"admin.view.news": true,	"admin.view.playlists": true,	"admin.view.punishments": true,	"admin.view.reports": true,	"admin.view.songs": true,	"admin.view.stations": true,	"admin.view.users": true,	"admin.view.youtubeVideos": true,	"apis.searchDiscogs": config.get("apis.discogs.enabled"),	"news.create": true,	"news.update": true,	"playlists.create.admin": true,	"playlists.get": true,	"playlists.update.displayName": true,	"playlists.update.privacy": true,	"playlists.songs.add": true,	"playlists.songs.remove": true,	"playlists.songs.reposition": true,	"playlists.view.others": true,	"punishments.banIP": true,	"punishments.get": true,	"reports.get": true,	"reports.update": true,	"songs.create": true,	"songs.get": true,	"songs.update": true,	"songs.verify": true,	"stations.create.official": true,	"stations.index": false,	"stations.index.other": true,	"stations.remove": false,	"users.get": true,	"users.ban": true,	"users.requestPasswordReset": config.get("mail.enabled"),	"users.resendVerifyEmail": config.get("mail.enabled"),	"users.update": true,	"youtube.requestSetAdmin": true,	...(config.get("experimental.soundcloud")		? {				"admin.view.soundcloudTracks": true,				"admin.view.soundcloud": true,				"soundcloud.getArtist": true		  }		: {}),	...(config.get("experimental.spotify")		? {				"admin.view.spotify": true,				"spotify.getTracksFromMediaSources": true,				"spotify.getAlbumsFromIds": true,				"spotify.getArtistsFromIds": true,				"spotify.getAlternativeArtistSourcesForArtists": true,				"spotify.getAlternativeAlbumSourcesForAlbums": true,				"spotify.getAlternativeMediaSourcesForTracks": true,				"admin.view.youtubeChannels": true,				"youtube.getChannel": true		  }		: {})};permissions.admin = {	...permissions.moderator,	"admin.view.dataRequests": true,	"admin.view.statistics": true,	"admin.view.youtube": true,	"dataRequests.resolve": true,	"media.recalculateAllRatings": true,	"media.removeImportJobs": true,	"news.remove": true,	"playlists.clearAndRefill": true,	"playlists.clearAndRefillAll": true,	"playlists.createMissing": true,	"playlists.deleteOrphaned": true,	"playlists.removeAdmin": true,	"playlists.requestOrphanedPlaylistSongs": true,	"punishments.deactivate": true,	"reports.remove": true,	"songs.remove": true,	"songs.updateAll": true,	"stations.clearEveryStationQueue": true,	"stations.remove": true,	"users.remove": true,	"users.remove.sessions": true,	"users.update.restricted": true,	"utils.getModules": true,	"youtube.getApiRequest": true,	"youtube.getMissingVideos": true,	"youtube.resetStoredApiRequests": true,	"youtube.removeStoredApiRequest": true,	"youtube.removeVideos": true,	"youtube.updateVideosV1ToV2": true,	...(config.get("experimental.soundcloud")		? {				"soundcloud.fetchNewApiKey": true,				"soundcloud.testApiKey": true		  }		: {}),	...(config.get("experimental.spotify")		? {				"youtube.getMissingChannels": true		  }		: {})};export const hasPermission = async (permission, session, stationId) => {	const CacheModule = moduleManager.modules.cache;	const DBModule = moduleManager.modules.db;	const StationsModule = moduleManager.modules.stations;	const UtilsModule = moduleManager.modules.utils;	const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);	return new Promise((resolve, reject) => {		async.waterfall(			[				next => {					let userId;					if (typeof session === "object") {						if (session.userId) userId = session.userId;						else							CacheModule.runJob(								"HGET",								{									table: "sessions",									key: session.sessionId								},								this							)								.then(_session => {									if (_session && _session.userId) userId = _session.userId;								})								.catch(next);					} else userId = session;					if (!userId) return next("User ID required.");					return userModel.findOne({ _id: userId }, next);				},				(user, next) => {					if (!user) return next("Login required.");					if (!stationId) return next(null, [user.role]);					return StationsModule.runJob("GET_STATION", { stationId }, this)						.then(station => {							if (!station) return next("Station not found.");							if (station.type === "community" && station.owner === user._id.toString())								return next(null, [user.role, "owner"]);							if (station.djs.find(dj => dj === user._id.toString()))								return next(null, [user.role, "dj"]);							if (user.role === "admin" || user.role === "moderator") return next(null, [user.role]);							return next("Invalid permissions.");						})						.catch(next);				},				(roles, next) => {					if (!roles) return next("Role required.");					let permissionFound;					roles.forEach(role => {						if (permissions[role] && permissions[role][permission]) permissionFound = true;					});					if (permissionFound) return next();					return next("Insufficient permissions.");				}			],			async err => {				const userId = typeof session === "object" ? session.userId || session.sessionId : session;				if (err) {					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);					UtilsModule.log(						"INFO",						"HAS_PERMISSION",						`User "${userId}" does not have required permission "${permission}". "${err}"`					);					return reject(err);				}				UtilsModule.log(					"INFO",					"HAS_PERMISSION",					`User "${userId}" has required permission "${permission}".`,					false				);				return resolve();			}		);	});};export const useHasPermission = (options, destination) =>	async function useHasPermission(session, ...args) {		const UtilsModule = moduleManager.modules.utils;		const permission = typeof options === "object" ? options.permission : options;		const cb = args[args.length - 1];		async.waterfall(			[				next => {					if (!session || !session.sessionId) return next("Login required.");					return hasPermission(permission, session)						.then(() => next())						.catch(next);				}			],			async err => {				if (err) {					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);					this.log(						"INFO",						"USE_HAS_PERMISSION",						`User "${session.userId}" does not have required permission "${permission}". "${err}"`					);					return cb({ status: "error", message: err });				}				this.log(					"INFO",					"USE_HAS_PERMISSION",					`User "${session.userId}" has required permission "${permission}".`,					false				);				return destination.apply(this, [session].concat(args));			}		);	};export const getUserPermissions = async (session, stationId) => {	const CacheModule = moduleManager.modules.cache;	const DBModule = moduleManager.modules.db;	const StationsModule = moduleManager.modules.stations;	const UtilsModule = moduleManager.modules.utils;	const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);	return new Promise((resolve, reject) => {		async.waterfall(			[				next => {					let userId;					if (typeof session === "object") {						if (session.userId) userId = session.userId;						else							CacheModule.runJob(								"HGET",								{									table: "sessions",									key: session.sessionId								},								this							)								.then(_session => {									if (_session && _session.userId) userId = _session.userId;								})								.catch(next);					} else userId = session;					if (!userId) return next("User ID required.");					return userModel.findOne({ _id: userId }, next);				},				(user, next) => {					if (!user) return next("Login required.");					if (!stationId) return next(null, [user.role]);					return StationsModule.runJob("GET_STATION", { stationId }, this)						.then(station => {							if (!station) return next("Station not found.");							if (station.type === "community" && station.owner === user._id.toString())								return next(null, [user.role, "owner"]);							if (station.djs.find(dj => dj === user._id.toString()))								return next(null, [user.role, "dj"]);							if (user.role === "admin" || user.role === "moderator") return next(null, [user.role]);							return next("Invalid permissions.");						})						.catch(next);				},				(roles, next) => {					if (!roles) return next("Role required.");					let rolePermissions = {};					roles.forEach(role => {						if (permissions[role]) rolePermissions = { ...rolePermissions, ...permissions[role] };					});					return next(null, rolePermissions);				}			],			async (err, rolePermissions) => {				const userId = typeof session === "object" ? session.userId || session.sessionId : session;				if (err) {					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);					UtilsModule.log(						"INFO",						"GET_USER_PERMISSIONS",						`Failed to get permissions for user "${userId}". "${err}"`					);					return reject(err);				}				UtilsModule.log("INFO", "GET_USER_PERMISSIONS", `Fetched permissions for user "${userId}".`, false);				return resolve(rolePermissions);			}		);	});};
 |