Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • alphabet/laboite
  • arthur.lutz/laboite
  • daniel.dehennin/laboite
  • olivier.heintz/laboite
4 results
Show changes
Showing
with 3047 additions and 740 deletions
...@@ -4,14 +4,15 @@ import { Roles } from 'meteor/alanning:roles'; ...@@ -4,14 +4,15 @@ import { Roles } from 'meteor/alanning:roles';
import i18n from 'meteor/universe:i18n'; import i18n from 'meteor/universe:i18n';
import crypto from 'crypto'; import crypto from 'crypto';
import { parseStringPromise } from 'xml2js'; import { parseStringPromise } from 'xml2js';
import logServer from '../logging'; import logServer, { levels, scopes } from '../logging';
import Groups from '../groups/groups'; import Groups from '../groups/groups';
import { testMeteorSettingsUrl } from '../../ui/utils/utilsFuncs';
const bbbEnabled = Meteor.settings.public.enableBBB; const bbbEnabled = Meteor.settings.public.enableBBB;
class BigBlueButtonClient { class BigBlueButtonClient {
constructor() { constructor() {
this.bbbURL = Meteor.settings.public.BBBUrl; this.bbbURL = testMeteorSettingsUrl(Meteor.settings.public.BBBUrl);
this.bbbSecret = Meteor.settings.private.BBBSecret; this.bbbSecret = Meteor.settings.private.BBBSecret;
} }
...@@ -74,19 +75,49 @@ class BigBlueButtonClient { ...@@ -74,19 +75,49 @@ class BigBlueButtonClient {
meeting: meetingData, meeting: meetingData,
}, },
}); });
// logServer(`meeting created: ${JSON.stringify(meetingData)}`); logServer(
`APPCLIENT - BBBCLIENT - UPDATE - createMeeting - meeting created: ${JSON.stringify(meetingData)}`,
levels.INFO,
scopes.SYSTEM,
{
meetingParams,
slug,
userId,
},
);
return Promise.resolve(this.getJoinURL(slug, userId)); return Promise.resolve(this.getJoinURL(slug, userId));
} }
if (result.response.messageKey[0] === 'idNotUnique') { if (result.response.messageKey[0] === 'idNotUnique') {
// a meeting has already been created, ignore this error // a meeting has already been created, ignore this error
return Promise.resolve(this.getJoinURL(slug, userId)); return Promise.resolve(this.getJoinURL(slug, userId));
} }
logServer(
`APPCLIENT - BBBCLIENT - METEOR ERROR - createMeeting
- BBB create meeting Error: ${result.response.messageKey[0]}`,
levels.INFO,
scopes.SYSTEM,
{
meetingParams,
slug,
userId,
},
);
// use messageKey if translation needed // use messageKey if translation needed
throw new Meteor.Error('api.BBBClient.createMeeting.error', result.response.messageKey[0]); throw new Meteor.Error('api.BBBClient.createMeeting.error', result.response.messageKey[0]);
}), }),
) )
.catch((err) => { .catch((err) => {
logServer(`BBB create error: ${err}`, 'error'); logServer(
`APPCLIENT - BBBCLIENT - METEOR ERROR - createMeeting
- BBB create error: ${err}`,
levels.ERROR,
scopes.SYSTEM,
{
slug,
userId,
meetingParams,
},
);
throw new Meteor.Error('api.BBBClient.createMeeting.error', i18n.__('api.bbb.createError')); throw new Meteor.Error('api.BBBClient.createMeeting.error', i18n.__('api.bbb.createError'));
}); });
} }
...@@ -130,12 +161,27 @@ class BigBlueButtonClient { ...@@ -130,12 +161,27 @@ class BigBlueButtonClient {
if (result.response.returncode[0] === 'SUCCESS') { if (result.response.returncode[0] === 'SUCCESS') {
return Promise.resolve(result.response.running); return Promise.resolve(result.response.running);
} }
logServer(
`APPCLIENT - BBBCLIENT - METEOR ERROR - checkRunning -
BBB check runnning: ${result.response.messageKey[0]}`,
levels.ERROR,
scopes.SYSTEM,
{},
);
// use messageKey if translation needed // use messageKey if translation needed
throw new Meteor.Error('api.BBBClient.checkRunning.error', result.response.messageKey[0]); throw new Meteor.Error('api.BBBClient.checkRunning.error', result.response.messageKey[0]);
}), }),
) )
.catch((err) => { .catch((err) => {
logServer(`BBB checkRunning Error: ${JSON.stringify(err)}`); logServer(
`APPCLIENT - BBBCLIENT - ERROR - checkRunning - BBB checkRunning Error: ${JSON.stringify(err)}`,
levels.ERROR,
scopes.SYSTEM,
{
slug,
groupId,
},
);
return Promise.resolve(null); return Promise.resolve(null);
}); });
} }
...@@ -155,12 +201,22 @@ class BigBlueButtonClient { ...@@ -155,12 +201,22 @@ class BigBlueButtonClient {
if (result.response.returncode[0] === 'SUCCESS') { if (result.response.returncode[0] === 'SUCCESS') {
return Promise.resolve(result.response.meetings); return Promise.resolve(result.response.meetings);
} }
logServer(
`APPCLIENT - BBBCLIENT - METEOR ERROR - getMeetings -
BBB message missing: ${result.response.messageKey[0]}`,
levels.WARN,
scopes.SYSTEM,
);
// use messageKey if translation needed // use messageKey if translation needed
throw new Meteor.Error('api.BBBClient.getMeetings.error', result.response.messageKey[0]); throw new Meteor.Error('api.BBBClient.getMeetings.error', result.response.messageKey[0]);
}), }),
) )
.catch((err) => { .catch((err) => {
logServer(`BBB getMeetings Error: ${JSON.stringify(err)}`); logServer(
`APPCLIENT - BBBCLIENT - ERROR - getMeetings - BBB getMeetings Error: ${JSON.stringify(err)}`,
levels.ERROR,
scopes.SYSTEM,
);
return Promise.resolve(null); return Promise.resolve(null);
}); });
} }
...@@ -169,10 +225,25 @@ class BigBlueButtonClient { ...@@ -169,10 +225,25 @@ class BigBlueButtonClient {
let Client = null; let Client = null;
if (Meteor.isServer && bbbEnabled) { if (Meteor.isServer && bbbEnabled) {
Client = new BigBlueButtonClient(); Client = new BigBlueButtonClient();
logServer(i18n.__('api.bbb.checkConfig', { URL: Client.bbbURL })); logServer(
`APPCLIENT - BBBCLIENT - NEW OBJECT - BigBlueButtonClient
- ${i18n.__('api.bbb.checkConfig', { URL: Client.bbbURL })}`,
levels.INFO,
scopes.SYSTEM,
{
URL: Client.bbbURL,
},
);
Client.getMeetings().then(() => { Client.getMeetings().then(() => {
// console.log('*** ALL MEETINGS : ', JSON.stringify(response)); logServer(
logServer(i18n.__('api.bbb.configOk')); `APPCLIENT - BBBCLIENT - THEN - getMeetings
- ${i18n.__('api.bbb.configOk')}`,
levels.INFO,
scopes.SYSTEM,
{
URL: Client.bbbURL,
},
);
}); });
} }
const BBBClient = Client; const BBBClient = Client;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import { Mongo } from 'meteor/mongo'; import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import { Tracker } from 'meteor/tracker';
import { getLabel } from '../utils'; import { getLabel } from '../utils';
const AppSettings = new Mongo.Collection('appsettings'); const AppSettings = new Mongo.Collection('appsettings');
...@@ -50,6 +49,19 @@ const IntroductionI18n = new SimpleSchema({ ...@@ -50,6 +49,19 @@ const IntroductionI18n = new SimpleSchema({
}, },
}); });
const GlobalInfoI18n = new SimpleSchema({
language: {
type: String,
label: getLabel('api.appsettings.labels.language'),
optional: true,
},
content: {
type: String,
label: getLabel('api.appsettings.labels.content_globalInfo'),
optional: true,
},
});
AppSettings.schema = new SimpleSchema( AppSettings.schema = new SimpleSchema(
{ {
introduction: { introduction: {
...@@ -59,6 +71,13 @@ AppSettings.schema = new SimpleSchema( ...@@ -59,6 +71,13 @@ AppSettings.schema = new SimpleSchema(
'introduction.$': { 'introduction.$': {
type: IntroductionI18n, type: IntroductionI18n,
}, },
globalInfo: {
type: Array,
label: getLabel('api.appsettings.labels.globalInfo'),
},
'globalInfo.$': {
type: GlobalInfoI18n,
},
legal: { legal: {
type: SettingsType('legal'), type: SettingsType('legal'),
label: getLabel('api.appsettings.labels.legal'), label: getLabel('api.appsettings.labels.legal'),
...@@ -75,6 +94,10 @@ AppSettings.schema = new SimpleSchema( ...@@ -75,6 +94,10 @@ AppSettings.schema = new SimpleSchema(
type: SettingsType('personal_data'), type: SettingsType('personal_data'),
label: getLabel('api.appsettings.labels.personal_data'), label: getLabel('api.appsettings.labels.personal_data'),
}, },
personalSpace: {
type: SettingsType('personal_space'),
label: getLabel('api.appsettings.labels.personalSpace'),
},
maintenance: { maintenance: {
type: Boolean, type: Boolean,
defaultValue: false, defaultValue: false,
...@@ -85,24 +108,35 @@ AppSettings.schema = new SimpleSchema( ...@@ -85,24 +108,35 @@ AppSettings.schema = new SimpleSchema(
defaultValue: ' ', defaultValue: ' ',
label: getLabel('api.appsettings.labels.textMaintenance'), label: getLabel('api.appsettings.labels.textMaintenance'),
}, },
userStructureValidationMandatory: {
type: Boolean,
label: getLabel('api.appsettings.label.userStructureValidationMandatory'),
},
}, },
{ clean: { removeEmptyStrings: false }, tracker: Tracker }, { clean: { removeEmptyStrings: false } },
); );
AppSettings.publicFields = { AppSettings.publicFields = {
introduction: 1, introduction: 1,
legal: 1, legal: 1,
globalInfo: 1,
accessibility: 1, accessibility: 1,
gcu: 1, gcu: 1,
personalData: 1, personalData: 1,
maintenance: 1, maintenance: 1,
textMaintenance: 1, textMaintenance: 1,
userStructureValidationMandatory: 1,
personalSpace: 1,
}; };
AppSettings.introduction = { AppSettings.introduction = {
'introduction.content': 1, 'introduction.content': 1,
'introduction.language': 1, 'introduction.language': 1,
}; };
AppSettings.globalInfo = {
'globalInfo.content': 1,
'globalInfo.language': 1,
};
AppSettings.links = { AppSettings.links = {
'legal.link': 1, 'legal.link': 1,
'legal.external': 1, 'legal.external': 1,
...@@ -112,6 +146,8 @@ AppSettings.links = { ...@@ -112,6 +146,8 @@ AppSettings.links = {
'gcu.external': 1, 'gcu.external': 1,
'personalData.link': 1, 'personalData.link': 1,
'personalData.external': 1, 'personalData.external': 1,
'personalSpace.link': 1,
'personalSpace.external': 1,
}; };
AppSettings.legal = { AppSettings.legal = {
...@@ -134,6 +170,11 @@ AppSettings.personalData = { ...@@ -134,6 +170,11 @@ AppSettings.personalData = {
'personalData.external': 1, 'personalData.external': 1,
'personalData.content': 1, 'personalData.content': 1,
}; };
AppSettings.personalSpace = {
'personalSpace.link': 1,
'personalSpace.external': 1,
'personalSpace.content': 1,
};
AppSettings.attachSchema(AppSettings.schema); AppSettings.attachSchema(AppSettings.schema);
......
import { useTracker } from 'meteor/react-meteor-data'; import { useTracker } from 'meteor/react-meteor-data';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import AppSettings from './appsettings'; import AppSettings from './appsettings';
import { getCurrentIntroduction } from '../utils'; import { getCurrentIntroduction, getCurrentText } from '../utils';
export const useCurrentIntroduction = () => export const useCurrentIntroduction = () =>
useTracker(() => { useTracker(() => {
...@@ -14,3 +14,15 @@ export const useCurrentIntroduction = () => ...@@ -14,3 +14,15 @@ export const useCurrentIntroduction = () =>
return { data, loading }; return { data, loading };
}); });
export const useCurrentGlobalInfo = () =>
useTracker(() => {
const handle = Meteor.subscribe('appsettings.globalInfo');
const loading = !handle.ready();
const appsettings = AppSettings.findOne() || {};
const { globalInfo = [] } = appsettings;
const data = getCurrentText({ data: globalInfo });
return { data, loading };
});
...@@ -6,14 +6,20 @@ import SimpleSchema from 'simpl-schema'; ...@@ -6,14 +6,20 @@ import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { Roles } from 'meteor/alanning:roles'; import { Roles } from 'meteor/alanning:roles';
import i18n from 'meteor/universe:i18n'; import i18n from 'meteor/universe:i18n';
import logServer from '../logging'; import sanitizeHtml from 'sanitize-html';
import { isActive, getLabel } from '../utils'; import logServer, { levels, scopes } from '../logging';
import { isActive, getLabel, validateString, sanitizeParameters } from '../utils';
import AppSettings from './appsettings'; import AppSettings from './appsettings';
export function checkMigrationStatus() { export function checkMigrationStatus() {
if (Migrations._getControl().locked === true) { if (Migrations._getControl().locked === true) {
logServer('Migration lock detected !!!!', 'error'); logServer(
`APPSETTINGS - METHODS - UPDATE - checkMigrationStatus,Migration lock detected !!!!`,
levels.WARN,
scopes.SYSTEM,
);
AppSettings.update({}, { $set: { maintenance: true, textMaintenance: 'api.appsettings.migrationLockedText' } }); AppSettings.update({}, { $set: { maintenance: true, textMaintenance: 'api.appsettings.migrationLockedText' } });
} }
} }
...@@ -43,14 +49,33 @@ export const updateAppsettings = new ValidatedMethod({ ...@@ -43,14 +49,33 @@ export const updateAppsettings = new ValidatedMethod({
run({ external, link, content, key }) { run({ external, link, content, key }) {
try { try {
if (link) validateString(link);
let sanitizedContent = '';
if (content) {
sanitizedContent = sanitizeHtml(content, sanitizeParameters);
validateString(sanitizedContent);
}
validateString(key, true);
// check if current user is admin // check if current user is admin
const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin'); const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin');
if (!authorized) { if (!authorized) {
throw new Meteor.Error('api.appsettings.updateAppsettings.notPermitted', i18n.__('api.users.adminNeeded')); throw new Meteor.Error('api.appsettings.updateAppsettings.notPermitted', i18n.__('api.users.adminNeeded'));
} }
const args = { content, external, link }; const args = { content: sanitizedContent, external, link };
logServer(
`APPSETTINGS - METHODS - UPDATE - updateAppsettings - args: ${JSON.stringify(args)}`,
levels.VERBOSE,
scopes.SYSTEM,
{ external, link, content, key },
);
return AppSettings.update({ _id: 'settings' }, { $set: { [key]: args } }); return AppSettings.update({ _id: 'settings' }, { $set: { [key]: args } });
} catch (error) { } catch (error) {
logServer(
`APPSETTINGS - METHODS - METEOR ERROR - updateAppsettings - error: ${error}`,
levels.ERROR,
scopes.SYSTEM,
{ external, link, content, key },
);
throw new Meteor.Error(error, error); throw new Meteor.Error(error, error);
} }
}, },
...@@ -86,8 +111,59 @@ export const switchMaintenanceStatus = new ValidatedMethod({ ...@@ -86,8 +111,59 @@ export const switchMaintenanceStatus = new ValidatedMethod({
checkMigrationStatus(); checkMigrationStatus();
return AppSettings.update({ _id: 'settings' }, { $set: { maintenance: newValue, textMaintenance: '' } }); return AppSettings.update({ _id: 'settings' }, { $set: { maintenance: newValue, textMaintenance: '' } });
} }
logServer(
`APPSETTINGS - METHODS - UPDATE - switchMaintenanceStatus - Maintenance: ${newValue}`,
levels.VERBOSE,
scopes.SYSTEM,
{ unlockMigration },
);
return AppSettings.update({ _id: 'settings' }, { $set: { maintenance: newValue } }); return AppSettings.update({ _id: 'settings' }, { $set: { maintenance: newValue } });
} catch (error) { } catch (error) {
logServer(`APPSETTINGS - METHODS - METEOR ERROR - switchMaintenanceStatus`, levels.ERROR, scopes.SYSTEM, {
error,
});
throw new Meteor.Error(error, error);
}
},
});
export const setUserStructureValidationMandatoryStatus = new ValidatedMethod({
name: 'appSettings.setUserStructureValidationMandatoryStatus',
validate: new SimpleSchema({ isValidationMandatory: { type: Boolean } }).validator(),
run({ isValidationMandatory }) {
try {
const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin');
if (!authorized) {
logServer(
`APPSETTINGS - METHODS - METEOR ERROR - setUserStructureValidationMandatoryStatus -
authorized: ${authorized}`,
levels.ERROR,
scopes.SYSTEM,
{ isValidationMandatory },
);
throw new Meteor.Error(
'api.appsettings.setUserStructureValidationMandatoryStatus.notPermitted',
i18n.__('api.users.admineeded'),
);
}
logServer(
`APPSETTINGS - METHODS - UPDATE - setUserStructureValidationMandatoryStatus -
isValidationMandatory: ${isValidationMandatory}`,
levels.VERBOSE,
scopes.SYSTEM,
{ isValidationMandatory },
);
return AppSettings.update(
{ _id: 'settings' },
{ $set: { userStructureValidationMandatory: isValidationMandatory } },
);
} catch (error) {
logServer(
`APPSETTINGS - METHODS - METEOR ERROR - setUserStructureValidationMandatoryStatus`,
levels.ERROR,
scopes.SYSTEM,
{ error },
);
throw new Meteor.Error(error, error); throw new Meteor.Error(error, error);
} }
}, },
...@@ -104,21 +180,29 @@ export const updateTextMaintenance = new ValidatedMethod({ ...@@ -104,21 +180,29 @@ export const updateTextMaintenance = new ValidatedMethod({
}).validator({ clean: true }), }).validator({ clean: true }),
run({ text }) { run({ text }) {
if (text) validateString(text);
try { try {
// check if current user is admin // check if current user is admin
const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin'); const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin');
if (!authorized) { if (!authorized) {
throw new Meteor.Error('api.appsettings.updateTextMaintenance.notPermitted', i18n.__('api.users.adminNeeded')); throw new Meteor.Error('api.appsettings.updateTextMaintenance.notPermitted', i18n.__('api.users.adminNeeded'));
} }
logServer(
`APPSETTINGS - METHODS - UPDATE - updateTextMaintenance - text maintenance: ${text}`,
levels.INFO,
scopes.SYSTEM,
{ text },
);
return AppSettings.update({ _id: 'settings' }, { $set: { textMaintenance: text } }); return AppSettings.update({ _id: 'settings' }, { $set: { textMaintenance: text } });
} catch (error) { } catch (error) {
logServer(`APPSETTINGS - METHODS - METEOR ERROR - updateTextMaintenance`, levels.ERROR, scopes.SYSTEM, { error });
throw new Meteor.Error(error, error); throw new Meteor.Error(error, error);
} }
}, },
}); });
export const updateIntroductionLanguage = new ValidatedMethod({ export const updateTextInfoLanguage = new ValidatedMethod({
name: 'appSettings.updateIntroductionLanguage', name: 'appSettings.updateTextInfoLanguage',
validate: new SimpleSchema({ validate: new SimpleSchema({
language: { language: {
type: String, type: String,
...@@ -130,29 +214,64 @@ export const updateIntroductionLanguage = new ValidatedMethod({ ...@@ -130,29 +214,64 @@ export const updateIntroductionLanguage = new ValidatedMethod({
label: getLabel('api.appsettings.labels.content'), label: getLabel('api.appsettings.labels.content'),
optional: true, optional: true,
}, },
tabkey: {
type: String,
label: getLabel('api.appsettings.labels.tabkey'),
optional: true,
},
}).validator({ clean: true }), }).validator({ clean: true }),
run({ language, content }) { run({ language, content, tabkey }) {
if (language) validateString(language, true);
if (tabkey) validateString(tabkey, true);
let sanitizedContent = '';
if (content) {
sanitizedContent = sanitizeHtml(content, sanitizeParameters);
validateString(sanitizedContent);
}
try { try {
// check if current user is admin // check if current user is admin
const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin'); const authorized = isActive(this.userId) && Roles.userIsInRole(this.userId, 'admin');
if (!authorized) { if (!authorized) {
logServer(
`APPSETTINGS - METHODS - METEOR ERROR - updateTextInfoLanguage - authorized: ${authorized}`,
levels.ERROR,
scopes.SYSTEM,
);
throw new Meteor.Error( throw new Meteor.Error(
'api.appsettings.updateIntroductionLanguage.notPermitted', 'api.appsettings.updateIntroductionLanguage.notPermitted',
i18n.__('api.users.adminNeeded'), i18n.__('api.users.adminNeeded'),
); );
} }
const appsettings = AppSettings.findOne({}); const appsettings = AppSettings.findOne({});
const { introduction } = appsettings; let newInfo;
const langIndex = introduction.findIndex((entry) => entry.language === language); let langIndex;
const newIntro = [...introduction]; if (tabkey === 'globalInfo') {
const { globalInfo } = appsettings;
newInfo = [...globalInfo];
langIndex = globalInfo.findIndex((entry) => entry.language === language);
} else if (tabkey === 'introduction') {
const { introduction } = appsettings;
newInfo = [...introduction];
langIndex = introduction.findIndex((entry) => entry.language === language);
}
if (langIndex > -1) { if (langIndex > -1) {
newIntro[langIndex].content = content; newInfo[langIndex].content = sanitizedContent;
} else { } else {
newIntro.push({ language, content }); newInfo.push({ language, content: sanitizedContent });
} }
return AppSettings.update({ _id: 'settings' }, { $set: { introduction: newIntro } }); logServer(
`APPSETTINGS - METHODS - UPDATE - updateTextInfoLanguage - new settings: ${JSON.stringify(newInfo)}`,
levels.VERBOSE,
scopes.SYSTEM,
{ language, content, tabkey },
);
return AppSettings.update({ _id: 'settings' }, { $set: { [tabkey]: newInfo } });
} catch (error) { } catch (error) {
logServer(`APPSETTINGS - METHODS - METEOR ERROR - updateTextInfoLanguage`, levels.ERROR, scopes.SYSTEM, {
error,
});
throw new Meteor.Error(error, error); throw new Meteor.Error(error, error);
} }
}, },
...@@ -172,7 +291,14 @@ export const getAppSettingsLinks = new ValidatedMethod({ ...@@ -172,7 +291,14 @@ export const getAppSettingsLinks = new ValidatedMethod({
// Get list of all method names on User // Get list of all method names on User
const LISTS_METHODS = _.pluck( const LISTS_METHODS = _.pluck(
[updateAppsettings, updateIntroductionLanguage, updateTextMaintenance, switchMaintenanceStatus, getAppSettingsLinks], [
updateAppsettings,
updateTextMaintenance,
updateTextInfoLanguage,
switchMaintenanceStatus,
getAppSettingsLinks,
setUserStructureValidationMandatoryStatus,
],
'name', 'name',
); );
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
import { PublicationCollector } from 'meteor/johanbrook:publication-collector'; import { PublicationCollector } from 'meteor/johanbrook:publication-collector';
import { assert } from 'chai'; import { assert } from 'chai';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { Random } from 'meteor/random';
import '../../../startup/i18n/en.i18n.json'; import '../../../startup/i18n/en.i18n.json';
import faker from 'faker'; import { faker } from '@faker-js/faker';
import { Factory } from 'meteor/dburles:factory'; import { Factory } from 'meteor/dburles:factory';
import { Accounts } from 'meteor/accounts-base'; import { Accounts } from 'meteor/accounts-base';
import { Roles } from 'meteor/alanning:roles'; import { Roles } from 'meteor/alanning:roles';
...@@ -13,10 +14,10 @@ import { Roles } from 'meteor/alanning:roles'; ...@@ -13,10 +14,10 @@ import { Roles } from 'meteor/alanning:roles';
import AppSettings from '../appsettings'; import AppSettings from '../appsettings';
import { import {
updateAppsettings, updateAppsettings,
updateIntroductionLanguage,
getAppSettingsLinks, getAppSettingsLinks,
switchMaintenanceStatus, switchMaintenanceStatus,
updateTextMaintenance, updateTextMaintenance,
updateTextInfoLanguage,
} from '../methods'; } from '../methods';
import './publications'; import './publications';
import './factories'; import './factories';
...@@ -37,6 +38,10 @@ describe('appsettings', function () { ...@@ -37,6 +38,10 @@ describe('appsettings', function () {
{ language: 'en', content: 'Hello' }, { language: 'en', content: 'Hello' },
{ language: 'fr', content: 'Salut' }, { language: 'fr', content: 'Salut' },
], ],
globalInfo: [
{ language: 'en', content: 'Hello' },
{ language: 'fr', content: 'Salut' },
],
gcu: { gcu: {
external: false, external: false,
link: 'gcu_link', link: 'gcu_link',
...@@ -57,6 +62,12 @@ describe('appsettings', function () { ...@@ -57,6 +62,12 @@ describe('appsettings', function () {
link: 'pdata_link', link: 'pdata_link',
content: 'pdata_content', content: 'pdata_content',
}, },
userStructureValidationMandatory: false,
personalSpace: {
external: false,
link: 'pSpaceData_link',
content: 'pSpaceData_content',
},
}; };
AppSettings.insert(appsettinit); AppSettings.insert(appsettinit);
}); });
...@@ -67,10 +78,15 @@ describe('appsettings', function () { ...@@ -67,10 +78,15 @@ describe('appsettings', function () {
assert.equal(collections.appsettings.length, 1); assert.equal(collections.appsettings.length, 1);
const appall = collections.appsettings[0]; const appall = collections.appsettings[0];
assert.property(appall, 'introduction'); assert.property(appall, 'introduction');
assert.property(appall, 'globalInfo');
assert.property(appall, 'gcu'); assert.property(appall, 'gcu');
assert.property(appall, 'legal'); assert.property(appall, 'legal');
assert.property(appall, 'accessibility'); assert.property(appall, 'accessibility');
assert.property(appall, 'personalData'); assert.property(appall, 'personalData');
assert.property(appall, 'personalSpace');
assert.property(appall, 'maintenance');
assert.property(appall, 'textMaintenance');
assert.property(appall, 'userStructureValidationMandatory');
done(); done();
}); });
}); });
...@@ -87,6 +103,18 @@ describe('appsettings', function () { ...@@ -87,6 +103,18 @@ describe('appsettings', function () {
}); });
}); });
}); });
describe('appsettings.globalInfo', function () {
it('sends the appsetting globalInfo', function (done) {
const collector = new PublicationCollector({});
collector.collect('appsettings.globalInfo', {}, (collections) => {
const appinfo = collections.appsettings[0];
assert.property(appinfo, 'globalInfo');
assert.typeOf(appinfo.globalInfo, 'array');
assert.lengthOf(appinfo.globalInfo, 2);
done();
});
});
});
describe('appsettings.gcu', function () { describe('appsettings.gcu', function () {
it('sends the appsetting gcu', function (done) { it('sends the appsetting gcu', function (done) {
const collector = new PublicationCollector({}); const collector = new PublicationCollector({});
...@@ -143,11 +171,26 @@ describe('appsettings', function () { ...@@ -143,11 +171,26 @@ describe('appsettings', function () {
}); });
}); });
}); });
describe('appsettings.personalSpace', function () {
it('sends the appsetting personalSpace', function (done) {
const collector = new PublicationCollector({});
collector.collect('appsettings.personalSpace', {}, (collections) => {
const apppersData = collections.appsettings[0];
assert.property(apppersData, 'personalSpace');
assert.typeOf(apppersData.personalSpace, 'object');
assert.property(apppersData.personalSpace, 'external');
assert.property(apppersData.personalSpace, 'link');
assert.property(apppersData.personalSpace, 'content');
done();
});
});
});
}); });
describe('methods', function () { describe('methods', function () {
let adminId; let adminId;
let userId; let userId;
beforeEach(function () { beforeEach(function () {
this.timeout(3000);
// Clear // Clear
AppSettings.remove({}); AppSettings.remove({});
Meteor.users.remove({}); Meteor.users.remove({});
...@@ -161,6 +204,10 @@ describe('appsettings', function () { ...@@ -161,6 +204,10 @@ describe('appsettings', function () {
{ language: 'en', content: 'Hello' }, { language: 'en', content: 'Hello' },
{ language: 'fr', content: 'Salut' }, { language: 'fr', content: 'Salut' },
], ],
globalInfo: [
{ language: 'en', content: 'Hello' },
{ language: 'fr', content: 'Salut' },
],
gcu: { gcu: {
external: false, external: false,
link: 'gcu_link', link: 'gcu_link',
...@@ -181,6 +228,12 @@ describe('appsettings', function () { ...@@ -181,6 +228,12 @@ describe('appsettings', function () {
link: 'pdata_link', link: 'pdata_link',
content: 'pdata_content', content: 'pdata_content',
}, },
userStructureValidationMandatory: false,
personalSpace: {
external: false,
link: 'pSpaceData_link',
content: 'pSpaceData_content',
},
}; };
AppSettings.insert(appsettinit); AppSettings.insert(appsettinit);
...@@ -190,18 +243,18 @@ describe('appsettings', function () { ...@@ -190,18 +243,18 @@ describe('appsettings', function () {
email, email,
username: email, username: email,
password: 'toto', password: 'toto',
structure: faker.company.companyName(), structure: Random.id(),
firstName: faker.name.firstName(), firstName: faker.person.firstName(),
lastName: faker.name.lastName(), lastName: faker.person.lastName(),
}); });
const emailAdmin = faker.internet.email(); const emailAdmin = faker.internet.email();
adminId = Accounts.createUser({ adminId = Accounts.createUser({
email: emailAdmin, email: emailAdmin,
username: emailAdmin, username: emailAdmin,
password: 'toto', password: 'toto',
structure: faker.company.companyName(), structure: Random.id(),
firstName: faker.name.firstName(), firstName: faker.person.firstName(),
lastName: faker.name.lastName(), lastName: faker.person.lastName(),
}); });
// set this user as global admin // set this user as global admin
Roles.addUsersToRoles(adminId, 'admin'); Roles.addUsersToRoles(adminId, 'admin');
...@@ -226,23 +279,35 @@ describe('appsettings', function () { ...@@ -226,23 +279,35 @@ describe('appsettings', function () {
assert.equal(appsett.gcu.external, 0); assert.equal(appsett.gcu.external, 0);
}); });
}); });
describe('updateIntroductionLanguage', function () { describe('updateInfoLanguage', function () {
it('normal users can not update introduction language in app settings', function () { it('normal users can not update informations language in app settings', function () {
assert.throws( assert.throws(
() => { () => {
updateIntroductionLanguage._execute({ userId }, { language: 'fr', content: 'coucou' }); updateTextInfoLanguage._execute({ userId }, { tabkey: 'introduction', language: 'fr', content: 'coucou' });
}, },
Meteor.Error, Meteor.Error,
/api.appsettings.updateIntroductionLanguage.notPermitted/, /api.appsettings.updateIntroductionLanguage.notPermitted/,
); );
}); });
it('admin can update app settings', function () { it('admin can update app settings', function () {
updateIntroductionLanguage._execute({ userId: adminId }, { language: 'fr', content: 'coucou' }); updateTextInfoLanguage._execute(
{ userId: adminId },
{ tabkey: 'introduction', language: 'fr', content: 'coucou' },
);
updateTextInfoLanguage._execute(
{ userId: adminId },
{ tabkey: 'globalInfo', language: 'fr', content: 'salut' },
);
const appsett = AppSettings.findOne({ const appsett = AppSettings.findOne({
_id: 'settings', _id: 'settings',
introduction: { $elemMatch: { language: 'fr', content: 'coucou' } }, introduction: { $elemMatch: { language: 'fr', content: 'coucou' } },
}); });
assert.typeOf(appsett, 'object'); assert.typeOf(appsett, 'object');
const appsett2 = AppSettings.findOne({
_id: 'settings',
globalInfo: { $elemMatch: { language: 'fr', content: 'salut' } },
});
assert.typeOf(appsett2, 'object');
}); });
}); });
describe('getAppSettingsLinks', function () { describe('getAppSettingsLinks', function () {
......
import faker from 'faker'; import { faker } from '@faker-js/faker';
import { Factory } from 'meteor/dburles:factory'; import { Factory } from 'meteor/dburles:factory';
import AppSettings from '../appsettings'; import AppSettings from '../appsettings';
...@@ -14,6 +14,16 @@ Factory.define('appsettings', AppSettings, { ...@@ -14,6 +14,16 @@ Factory.define('appsettings', AppSettings, {
content: faker.lorem.sentences(), content: faker.lorem.sentences(),
}, },
], ],
globalInfo: [
{
language: 'en',
content: faker.lorem.sentences(),
},
{
language: 'fr',
content: faker.lorem.sentences(),
},
],
legal: { legal: {
external: Boolean(Math.random() * 2), external: Boolean(Math.random() * 2),
link: faker.lorem.slug(), link: faker.lorem.slug(),
...@@ -34,4 +44,10 @@ Factory.define('appsettings', AppSettings, { ...@@ -34,4 +44,10 @@ Factory.define('appsettings', AppSettings, {
link: faker.lorem.slug(), link: faker.lorem.slug(),
content: faker.lorem.sentences(), content: faker.lorem.sentences(),
}, },
userStructureValidationMandatory: false,
personalSpace: {
external: Boolean(Math.random() * 2),
link: faker.lorem.slug(),
content: faker.lorem.sentences(),
},
}); });
...@@ -13,6 +13,11 @@ Meteor.publish('appsettings.introduction', () => { ...@@ -13,6 +13,11 @@ Meteor.publish('appsettings.introduction', () => {
return AppSettings.find({ _id: 'settings' }, { fields: introduction, sort: { _id: 1 }, limit: 1 }); return AppSettings.find({ _id: 'settings' }, { fields: introduction, sort: { _id: 1 }, limit: 1 });
}); });
Meteor.publish('appsettings.globalInfo', () => {
const { globalInfo } = AppSettings;
return AppSettings.find({ _id: 'settings' }, { fields: globalInfo, sort: { _id: 1 }, limit: 1 });
});
// publish GCU settings // publish GCU settings
Meteor.publish('appsettings.gcu', () => { Meteor.publish('appsettings.gcu', () => {
const { gcu } = AppSettings; const { gcu } = AppSettings;
...@@ -37,6 +42,12 @@ Meteor.publish('appsettings.personalData', () => { ...@@ -37,6 +42,12 @@ Meteor.publish('appsettings.personalData', () => {
return AppSettings.find({ _id: 'settings' }, { fields: personalData, sort: { _id: 1 }, limit: 1 }); return AppSettings.find({ _id: 'settings' }, { fields: personalData, sort: { _id: 1 }, limit: 1 });
}); });
// publish personal space intro settings
Meteor.publish('appsettings.personalSpace', () => {
const { personalSpace } = AppSettings;
return AppSettings.find({ _id: 'settings' }, { fields: personalSpace, sort: { _id: 1 }, limit: 1 });
});
// publish maintenance settings // publish maintenance settings
Meteor.publish('appsettings.maintenance', () => { Meteor.publish('appsettings.maintenance', () => {
const { maintenance } = AppSettings; const { maintenance } = AppSettings;
...@@ -48,3 +59,12 @@ Meteor.publish('appsettings.textMaintenance', () => { ...@@ -48,3 +59,12 @@ Meteor.publish('appsettings.textMaintenance', () => {
const { textMaintenance } = AppSettings; const { textMaintenance } = AppSettings;
return AppSettings.find({ _id: 'settings' }, { fields: textMaintenance, sort: { _id: 1 }, limit: 1 }); return AppSettings.find({ _id: 'settings' }, { fields: textMaintenance, sort: { _id: 1 }, limit: 1 });
}); });
// publish userStructureValidationMandatory settings
Meteor.publish('appsettings.userStructureValidationMandatory', () => {
const { userStructureValidationMandatory } = AppSettings;
return AppSettings.find(
{ _id: 'settings' },
{ fields: userStructureValidationMandatory, sort: { _id: 1 }, limit: 1 },
);
});
/* eslint-disable func-names */ /* eslint-disable func-names */
import { Mongo } from 'meteor/mongo'; import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import { Tracker } from 'meteor/tracker';
import slugy from '../../ui/utils/slugy'; import slugy from '../../ui/utils/slugy';
import { getLabel } from '../utils'; import { getLabel } from '../utils';
import Groups from '../groups/groups'; import Groups from '../groups/groups';
import RegEx from '../regExp';
const Articles = new Mongo.Collection('articles'); const Articles = new Mongo.Collection('articles');
...@@ -57,7 +57,8 @@ Articles.schema = new SimpleSchema( ...@@ -57,7 +57,8 @@ Articles.schema = new SimpleSchema(
optional: true, optional: true,
}, },
structure: { structure: {
type: SimpleSchema.RegEx.Id, type: String,
// regEx: RegEx.Id, doesn't work, structure can be an empty string
label: getLabel('api.articles.labels.structure'), label: getLabel('api.articles.labels.structure'),
}, },
markdown: { type: Boolean, label: getLabel('api.articles.labels.markdown'), defaultValue: false }, markdown: { type: Boolean, label: getLabel('api.articles.labels.markdown'), defaultValue: false },
...@@ -74,11 +75,14 @@ Articles.schema = new SimpleSchema( ...@@ -74,11 +75,14 @@ Articles.schema = new SimpleSchema(
type: { type: Object }, type: { type: Object },
}, },
'groups.$._id': { 'groups.$._id': {
type: { type: String, regEx: SimpleSchema.RegEx.Id }, type: { type: String, regEx: RegEx.Id },
}, },
'groups.$.name': { 'groups.$.name': {
type: { type: String }, type: { type: String },
}, },
'groups.$.type': {
type: { type: SimpleSchema.Integer },
},
createdAt: { createdAt: {
type: Date, type: Date,
label: getLabel('api.articles.labels.createdAt'), label: getLabel('api.articles.labels.createdAt'),
...@@ -101,8 +105,12 @@ Articles.schema = new SimpleSchema( ...@@ -101,8 +105,12 @@ Articles.schema = new SimpleSchema(
type: SimpleSchema.Integer, type: SimpleSchema.Integer,
defaultValue: 0, defaultValue: 0,
}, },
licence: {
type: String,
defaultValue: '',
},
}, },
{ clean: { removeEmptyStrings: false }, tracker: Tracker }, { clean: { removeEmptyStrings: false } },
); );
Articles.publicFields = { Articles.publicFields = {
...@@ -119,6 +127,7 @@ Articles.publicFields = { ...@@ -119,6 +127,7 @@ Articles.publicFields = {
visits: 1, visits: 1,
tags: 1, tags: 1,
structure: 1, structure: 1,
licence: 1,
}; };
Articles.attachSchema(Articles.schema); Articles.attachSchema(Articles.schema);
......
This diff is collapsed.
import faker from 'faker'; import { faker } from '@faker-js/faker';
import { Factory } from 'meteor/dburles:factory'; import { Factory } from 'meteor/dburles:factory';
import { Random } from 'meteor/random'; import { Random } from 'meteor/random';
...@@ -9,5 +9,5 @@ Factory.define('article', Articles, { ...@@ -9,5 +9,5 @@ Factory.define('article', Articles, {
content: faker.lorem.sentence(), content: faker.lorem.sentence(),
description: faker.lorem.sentence().substring(0, 399), description: faker.lorem.sentence().substring(0, 399),
userId: () => Random.id(), userId: () => Random.id(),
structure: () => faker.company.companyName(), structure: () => faker.company.name(),
}); });
import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';
import { getLabel } from '../utils';
import RegEx from '../regExp';
const AsamExtensions = new Mongo.Collection('asamextensions');
AsamExtensions.deny({
insert() {
return true;
},
update() {
return true;
},
remove() {
return true;
},
});
/**
* About:
* `entiteNomCourt`, `entiteNomLong', `familleNomCourt`, `familleNomLong`
*
* These are used for helping admin user to think about the right structure to match
*
* These are not to be taken as truth or correct name for x or y structure
*/
AsamExtensions.schema = new SimpleSchema({
extension: {
type: String,
label: getLabel('api.asamextensions.labels.extension'),
min: 1,
},
entiteNomCourt: {
type: String,
label: getLabel('api.asamextensions.labels.entiteNomCourt'),
},
entiteNomLong: { type: String, label: getLabel('api.asamextensions.labels.entiteNomLong') },
familleNomCourt: { type: String, label: getLabel('api.asamextensions.labels.familleNomCourt') },
familleNomLong: { type: String, label: getLabel('api.asamextensions.labels.familleNomLong') },
structureId: {
type: String,
regEx: RegEx.Id,
label: getLabel('api.asamextensions.labels.structureId'),
defaultValue: null,
},
});
AsamExtensions.publicFields = {
extension: 1,
entiteNomCourt: 1,
entiteNomLong: 1,
familleNomCourt: 1,
familleNomLong: 1,
structureId: 1,
};
export default AsamExtensions;
This diff is collapsed.
import { Meteor } from 'meteor/meteor';
import AsamExtensions from '../asamextensions';
Meteor.publish('asamextensions.all', function getAllAsam() {
const searchResult = AsamExtensions.find(
{},
{
fields: AsamExtensions.publicFields,
sort: { extension: 1 },
limit: 10000,
},
);
return searchResult;
});
This diff is collapsed.