Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions app/authorization/server/functions/canAccessRoom.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import { hasPermission } from './hasPermission';
import { settings } from '../../../settings';
import Subscriptions from '../../../models/server/models/Subscriptions';
import { Subscriptions } from '../../../models/server/raw';
import { getValue } from '../../../settings/server/raw';

export const roomAccessValidators = [
function(room, user = {}) {
async function(room, user = {}) {
if (room && room.t === 'c') {
if (!user._id && settings.get('Accounts_AllowAnonymousRead') === true) {
const anonymous = await getValue('Accounts_AllowAnonymousRead');
if (!user._id && anonymous === true) {
return true;
}

return hasPermission(user._id, 'view-c-room');
}
},
function(room, user) {
async function(room, user) {
if (!room || !user) {
return;
}

const subscription = Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
if (subscription) {
return true;
}
},
];

export const canAccessRoom = (room, user, extraData) => roomAccessValidators.some((validator) => validator(room, user, extraData));
export const canAccessRoomAsync = async (room, user, extraData) => {
for (let i = 0, total = roomAccessValidators.length; i < total; i++) {
// eslint-disable-next-line no-await-in-loop
const permitted = await roomAccessValidators[i](room, user, extraData);
if (permitted) {
return true;
}
}
};

export const canAccessRoom = (room, user, extraData) => Promise.await(canAccessRoomAsync(room, user, extraData));

export const addRoomAccessValidator = (validator) => roomAccessValidators.push(validator.bind(this));
59 changes: 36 additions & 23 deletions app/authorization/server/functions/hasPermission.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import Roles from '../../../models/server/models/Roles';
import Permissions from '../../../models/server/models/Permissions';

function atLeastOne(userId, permissions = [], scope) {
return permissions.some((permissionId) => {
const permission = Permissions.findOne(permissionId);
return Roles.isUserInRoles(userId, permission.roles, scope);
});
import { Permissions, Roles } from '../../../models/server/raw';

async function atLeastOne(userId, permissions = [], scope) {
for (let i = 0, total = permissions.length; i < total; i++) {
const permissionId = permissions[i];

// eslint-disable-next-line no-await-in-loop
const permission = await Permissions.findOne({ _id: permissionId });
// eslint-disable-next-line no-await-in-loop
const found = await Roles.isUserInRoles(userId, permission.roles, scope);
if (found) {
return true;
}
}

return false;
}

function all(userId, permissions = [], scope) {
return permissions.every((permissionId) => {
const permission = Permissions.findOne(permissionId);
return Roles.isUserInRoles(userId, permission.roles, scope);
});
async function all(userId, permissions = [], scope) {
for (let i = 0, total = permissions.length; i < total; i++) {
const permissionId = permissions[i];

// eslint-disable-next-line no-await-in-loop
const permission = await Permissions.findOne({ _id: permissionId });
// eslint-disable-next-line no-await-in-loop
const found = await Roles.isUserInRoles(userId, permission.roles, scope);
if (!found) {
return false;
}
}

return true;
}

function _hasPermission(userId, permissions, scope, strategy) {
Expand All @@ -22,14 +39,10 @@ function _hasPermission(userId, permissions, scope, strategy) {
return strategy(userId, [].concat(permissions), scope);
}

export const hasAllPermission = (userId, permissions, scope) => _hasPermission(userId, permissions, scope, all);

export const hasPermission = (userId, permissionId, scope) => {
if (!userId) {
return false;
}
const permission = Permissions.findOne(permissionId);
return Roles.isUserInRoles(userId, permission.roles, scope);
};
export const hasAllPermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, all);
export const hasPermissionAsync = async (userId, permissionId, scope) => _hasPermission(userId, permissionId, scope, all);
export const hasAtLeastOnePermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, atLeastOne);

export const hasAtLeastOnePermission = (userId, permissions, scope) => _hasPermission(userId, permissions, scope, atLeastOne);
export const hasAllPermission = (userId, permissions, scope) => Promise.await(hasAllPermissionAsync(userId, permissions, scope));
export const hasPermission = (userId, permissionId, scope) => Promise.await(hasPermissionAsync(userId, permissionId, scope));
export const hasAtLeastOnePermission = (userId, permissions, scope) => Promise.await(hasAtLeastOnePermissionAsync(userId, permissions, scope));
20 changes: 14 additions & 6 deletions app/authorization/server/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { addUserRoles } from './functions/addUserRoles';
import { addRoomAccessValidator, canAccessRoom, roomAccessValidators } from './functions/canAccessRoom';
import {
addRoomAccessValidator,
canAccessRoom,
roomAccessValidators,
} from './functions/canAccessRoom';
import { canSendMessage } from './functions/canSendMessage';
import { getRoles } from './functions/getRoles';
import { getUsersInRole } from './functions/getUsersInRole';
import { hasAllPermission, hasAtLeastOnePermission, hasPermission } from './functions/hasPermission';
import {
hasAllPermission,
hasAtLeastOnePermission,
hasPermission,
} from './functions/hasPermission';
import { hasRole } from './functions/hasRole';
import { removeUserFromRoles } from './functions/removeUserFromRoles';
import './methods/addPermissionToRole';
Expand All @@ -20,14 +28,14 @@ import './startup';
export {
getRoles,
getUsersInRole,
hasAllPermission,
hasAtLeastOnePermission,
hasPermission,
hasRole,
removeUserFromRoles,
canAccessRoom,
canSendMessage,
addRoomAccessValidator,
roomAccessValidators,
addUserRoles,
canAccessRoom,
hasAllPermission,
hasAtLeastOnePermission,
hasPermission,
};
2 changes: 1 addition & 1 deletion app/authorization/server/methods/addPermissionToRole.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { Permissions } from '../../../models';
import { Permissions } from '../../../models/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
6 changes: 3 additions & 3 deletions app/authorization/server/methods/addUserToRole.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';

import { Users, Roles } from '../../../models';
import { settings } from '../../../settings';
import { Notifications } from '../../../notifications';
import { Users, Roles } from '../../../models/server';
import { settings } from '../../../settings/server';
import { Notifications } from '../../../notifications/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
2 changes: 1 addition & 1 deletion app/authorization/server/methods/deleteRole.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import * as Models from '../../../models';
import * as Models from '../../../models/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { Permissions } from '../../../models';
import { Permissions } from '../../../models/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
6 changes: 3 additions & 3 deletions app/authorization/server/methods/removeUserFromRole.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';

import { Roles } from '../../../models';
import { settings } from '../../../settings';
import { Notifications } from '../../../notifications';
import { Roles } from '../../../models/server';
import { settings } from '../../../settings/server';
import { Notifications } from '../../../notifications/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
6 changes: 3 additions & 3 deletions app/authorization/server/methods/saveRole.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Meteor } from 'meteor/meteor';

import { Roles } from '../../../models';
import { settings } from '../../../settings';
import { Notifications } from '../../../notifications';
import { Roles } from '../../../models/server';
import { settings } from '../../../settings/server';
import { Notifications } from '../../../notifications/server';
import { hasPermission } from '../functions/hasPermission';

Meteor.methods({
Expand Down
2 changes: 1 addition & 1 deletion app/file-upload/server/lib/FileUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Match } from 'meteor/check';
import { TAPi18n } from 'meteor/tap:i18n';
import filesize from 'filesize';

import { settings } from '../../../settings';
import { settings } from '../../../settings/server';
import Uploads from '../../../models/server/models/Uploads';
import UserDataFiles from '../../../models/server/models/UserDataFiles';
import Avatars from '../../../models/server/models/Avatars';
Expand Down
13 changes: 13 additions & 0 deletions app/models/server/raw/BaseRaw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export class BaseRaw {
constructor(col) {
this.col = col;
}

findOne(...args) {
return this.col.findOne(...args);
}

findUsersInRoles() {
throw new Error('overwrite-function', 'You must overwrite this function in the extended classes');
}
}
4 changes: 4 additions & 0 deletions app/models/server/raw/Permissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { BaseRaw } from './BaseRaw';

export class PermissionsRaw extends BaseRaw {
}
25 changes: 25 additions & 0 deletions app/models/server/raw/Roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as Models from '..';

import { BaseRaw } from './BaseRaw';

export class RolesRaw extends BaseRaw {
async isUserInRoles(userId, roles, scope) {
roles = [].concat(roles);

for (let i = 0, total = roles.length; i < total; i++) {
const roleName = roles[i];

// eslint-disable-next-line no-await-in-loop
const role = await this.findOne({ _id: roleName });
const roleScope = (role && role.scope) || 'Users';
const model = Models[roleScope];

// eslint-disable-next-line no-await-in-loop
const permitted = await (model && model.isUserInRole && model.isUserInRole(userId, roleName, scope));
if (permitted) {
return true;
}
}
return false;
}
}
9 changes: 9 additions & 0 deletions app/models/server/raw/Settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { BaseRaw } from './BaseRaw';

export class SettingsRaw extends BaseRaw {
async getValueById(_id) {
const setting = await this.col.findOne({ _id }, { projection: { value: 1 } });

return setting.value;
}
}
26 changes: 26 additions & 0 deletions app/models/server/raw/Subscriptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BaseRaw } from './BaseRaw';

export class SubscriptionsRaw extends BaseRaw {
findOneByRoomIdAndUserId(roomId, userId, options) {
const query = {
rid: roomId,
'u._id': userId,
};

return this.col.findOne(query, options);
}

isUserInRole(userId, roleName, rid) {
if (rid == null) {
return;
}

const query = {
'u._id': userId,
rid,
roles: roleName,
};

return this.findOne(query, { fields: { roles: 1 } });
}
}
13 changes: 13 additions & 0 deletions app/models/server/raw/Users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { BaseRaw } from './BaseRaw';

export class UsersRaw extends BaseRaw {
findUsersInRoles(roles, scope, options) {
roles = [].concat(roles);

const query = {
roles: { $in: roles },
};

return this.find(query, options);
}
}
16 changes: 16 additions & 0 deletions app/models/server/raw/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import PermissionsModel from '../models/Permissions';
import { PermissionsRaw } from './Permissions';
import RolesModel from '../models/Roles';
import { RolesRaw } from './Roles';
import SubscriptionsModel from '../models/Subscriptions';
import { SubscriptionsRaw } from './Subscriptions';
import SettingsModel from '../models/Settings';
import { SettingsRaw } from './Settings';
import UsersModel from '../models/Users';
import { UsersRaw } from './Users';

export const Permissions = new PermissionsRaw(PermissionsModel.model.rawCollection());
export const Roles = new RolesRaw(RolesModel.model.rawCollection());
export const Subscriptions = new SubscriptionsRaw(SubscriptionsModel.model.rawCollection());
export const Settings = new SettingsRaw(SettingsModel.model.rawCollection());
export const Users = new UsersRaw(UsersModel.model.rawCollection());
1 change: 1 addition & 0 deletions app/settings/server/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { settings } from './functions/settings';
import './observer';

export {
settings,
Expand Down
19 changes: 19 additions & 0 deletions app/settings/server/observer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Meteor } from 'meteor/meteor';

import { Settings } from '../../models/server';
import { setValue } from './raw';

const updateValue = (id, fields) => {
if (typeof fields.value === 'undefined') {
return;
}
setValue(id, fields.value);
};

Meteor.startup(() => Settings.find({}, { fields: { value: 1 } }).observeChanges({
added: updateValue,
changed: updateValue,
removed(id) {
setValue(id, undefined);
},
}));
21 changes: 21 additions & 0 deletions app/settings/server/raw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Settings } from '../../models/server/raw';

const cache = new Map();

export const setValue = (_id, value) => cache.set(_id, value);

const setFromDB = async (_id) => {
const value = await Settings.getValueById(_id);

setValue(_id, value);

return value;
};

export const getValue = async (_id) => {
if (!cache.has(_id)) {
return setFromDB(_id);
}

return cache.get(_id);
};
Loading