mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-21 15:54:22 +01:00
(ui) Option to prevent users from changing their group
This commit is contained in:
parent
1d2b814d6f
commit
e45872956c
@ -3,9 +3,13 @@
|
|||||||
## next deploy
|
## next deploy
|
||||||
|
|
||||||
- Option to disable the 'machines' module
|
- Option to disable the 'machines' module
|
||||||
|
- Option to prevent users from changing their group
|
||||||
- Ability to define social networks for the FabLab "about page"
|
- Ability to define social networks for the FabLab "about page"
|
||||||
|
- Improved security when changing passwords
|
||||||
- Support for OpenID Connect in Sign-Sign-On authentication providers
|
- Support for OpenID Connect in Sign-Sign-On authentication providers
|
||||||
- ICS file attached to the reservation notification email
|
- ICS file attached to the reservation notification email
|
||||||
|
- Refactored the user profile edition form
|
||||||
|
- Improved the profile completion page
|
||||||
- No longer needed to recompile the assets when switching the authentication provider
|
- No longer needed to recompile the assets when switching the authentication provider
|
||||||
- Updated the documentation about the minimum docker version
|
- Updated the documentation about the minimum docker version
|
||||||
- Updated nodejs version to 16.13.2 for dev environment, to reflect production version
|
- Updated nodejs version to 16.13.2 for dev environment, to reflect production version
|
||||||
|
@ -10,6 +10,9 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { FormSelect } from '../form/form-select';
|
import { FormSelect } from '../form/form-select';
|
||||||
import MemberAPI from '../../api/member';
|
import MemberAPI from '../../api/member';
|
||||||
|
import SettingAPI from '../../api/setting';
|
||||||
|
import { SettingName } from '../../models/setting';
|
||||||
|
import UserLib from '../../lib/user';
|
||||||
|
|
||||||
declare const Application: IApplication;
|
declare const Application: IApplication;
|
||||||
|
|
||||||
@ -18,6 +21,7 @@ interface ChangeGroupProps {
|
|||||||
onSuccess: (message: string, user: User) => void,
|
onSuccess: (message: string, user: User) => void,
|
||||||
onError: (message: string) => void,
|
onError: (message: string) => void,
|
||||||
allowChange?: boolean,
|
allowChange?: boolean,
|
||||||
|
className?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,18 +30,22 @@ interface ChangeGroupProps {
|
|||||||
*/
|
*/
|
||||||
type selectOption = { value: number, label: string };
|
type selectOption = { value: number, label: string };
|
||||||
|
|
||||||
export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onError, allowChange }) => {
|
export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onError, allowChange, className }) => {
|
||||||
const { t } = useTranslation('shared');
|
const { t } = useTranslation('shared');
|
||||||
|
|
||||||
const [groups, setGroups] = useState<Array<Group>>([]);
|
const [groups, setGroups] = useState<Array<Group>>([]);
|
||||||
const [changeRequested, setChangeRequested] = useState<boolean>(false);
|
const [changeRequested, setChangeRequested] = useState<boolean>(false);
|
||||||
const [operator, setOperator] = useState<User>(null);
|
const [operator, setOperator] = useState<User>(null);
|
||||||
|
const [allowedUserChangeGoup, setAllowedUserChangeGoup] = useState<boolean>(false);
|
||||||
|
|
||||||
const { handleSubmit, control } = useForm();
|
const { handleSubmit, control } = useForm();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
GroupAPI.index({ disabled: false, admins: false }).then(setGroups).catch(onError);
|
GroupAPI.index({ disabled: false, admins: false }).then(setGroups).catch(onError);
|
||||||
MemberAPI.current().then(setOperator).catch(onError);
|
MemberAPI.current().then(setOperator).catch(onError);
|
||||||
|
SettingAPI.get(SettingName.UserChangeGroup).then((setting) => {
|
||||||
|
setAllowedUserChangeGoup(setting.value === 'true');
|
||||||
|
}).catch(onError);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -55,7 +63,8 @@ export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onErr
|
|||||||
* Check if the group changing is currently allowed.
|
* Check if the group changing is currently allowed.
|
||||||
*/
|
*/
|
||||||
const canChangeGroup = (): boolean => {
|
const canChangeGroup = (): boolean => {
|
||||||
return allowChange;
|
const userLib = new UserLib(operator);
|
||||||
|
return allowChange && (allowedUserChangeGoup || userLib.isPrivileged(user));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,7 +90,7 @@ export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onErr
|
|||||||
if (!user) return null;
|
if (!user) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="change-group">
|
<div className={`change-group ${className || ''}`}>
|
||||||
<h3>{t('app.shared.change_group.title', { OPERATOR: operator?.id === user.id ? 'self' : 'admin' })}</h3>
|
<h3>{t('app.shared.change_group.title', { OPERATOR: operator?.id === user.id ? 'self' : 'admin' })}</h3>
|
||||||
{!changeRequested && <div className="display">
|
{!changeRequested && <div className="display">
|
||||||
<div className="current-group">
|
<div className="current-group">
|
||||||
@ -114,4 +123,4 @@ const ChangeGroupWrapper: React.FC<ChangeGroupProps> = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Application.Components.component('changeGroup', react2angular(ChangeGroupWrapper, ['user', 'onSuccess', 'onError', 'allowChange']));
|
Application.Components.component('changeGroup', react2angular(ChangeGroupWrapper, ['user', 'onSuccess', 'onError', 'allowChange', 'className']));
|
||||||
|
@ -140,20 +140,24 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the group of the current user to the one set in $scope.userGroup
|
* Callback triggered when the user has successfully changed his group
|
||||||
*/
|
*/
|
||||||
$scope.selectGroup = () =>
|
$scope.onGroupUpdateSuccess = function (message, user) {
|
||||||
Member.update({ id: $scope.user.id }, { user: { group_id: $scope.userGroup } }, function (user) {
|
growl.success(message);
|
||||||
$scope.user = user;
|
setTimeout(() => {
|
||||||
$rootScope.currentUser = user;
|
$scope.user = _.cloneDeep(user);
|
||||||
Auth._currentUser.group_id = user.group_id;
|
$scope.$apply();
|
||||||
$scope.group.change = false;
|
}, 50);
|
||||||
return growl.success(_t('app.logged.dashboard.settings.your_group_has_been_successfully_changed'));
|
$rootScope.currentUser.group_id = user.group_id;
|
||||||
}
|
Auth._currentUser.group_id = user.group_id;
|
||||||
, function (err) {
|
};
|
||||||
growl.error(_t('app.logged.dashboard.settings.an_unexpected_error_prevented_your_group_from_being_changed'));
|
|
||||||
return console.error(err);
|
/**
|
||||||
});
|
* Check if it is allowed the change the group of the current user
|
||||||
|
*/
|
||||||
|
$scope.isAllowedChangingGroup = function () {
|
||||||
|
return !$scope.user.subscribed_plan?.name && $scope.user.role !== 'admin';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to diplay the datepicker as a dropdown when clicking on the input field
|
* Callback to diplay the datepicker as a dropdown when clicking on the input field
|
||||||
|
@ -16,16 +16,6 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
function ($scope, $rootScope, $state, $uibModal, Auth, AuthService, dialogs, growl, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers, settingsPromise, Price) {
|
function ($scope, $rootScope, $state, $uibModal, Auth, AuthService, dialogs, growl, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers, settingsPromise, Price) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// list of groups
|
|
||||||
$scope.groups = groupsPromise.filter(function (g) { return (g.slug !== 'admins') & !g.disabled; });
|
|
||||||
|
|
||||||
// default : do not show the group changing form
|
|
||||||
// group ID of the current/selected user
|
|
||||||
$scope.group = {
|
|
||||||
change: false,
|
|
||||||
id: null
|
|
||||||
};
|
|
||||||
|
|
||||||
// user to deal with
|
// user to deal with
|
||||||
$scope.ctrl = {
|
$scope.ctrl = {
|
||||||
member: null,
|
member: null,
|
||||||
@ -59,10 +49,8 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
$scope.updateMember = function () {
|
$scope.updateMember = function () {
|
||||||
$scope.selectedPlan = null;
|
$scope.selectedPlan = null;
|
||||||
$scope.paid.plan = null;
|
$scope.paid.plan = null;
|
||||||
$scope.group.change = false;
|
|
||||||
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||||
$scope.ctrl.member = member;
|
$scope.ctrl.member = member;
|
||||||
$scope.group.id = $scope.ctrl.member.group_id;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,56 +92,6 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
growl.error(message);
|
growl.error(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the group object, identified by the ID set in $scope.group.id
|
|
||||||
*/
|
|
||||||
$scope.getUserGroup = function () {
|
|
||||||
for (const group of Array.from($scope.groups)) {
|
|
||||||
if (group.id === $scope.group.id) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the group of the current/selected user to the one set in $scope.group.id
|
|
||||||
*/
|
|
||||||
$scope.selectGroup = function () {
|
|
||||||
Member.update({ id: $scope.ctrl.member.id }, { user: { group_id: $scope.group.id } }, function (user) {
|
|
||||||
$scope.ctrl.member = user;
|
|
||||||
$scope.group.change = false;
|
|
||||||
$scope.selectedPlan = null;
|
|
||||||
if (AuthService.isAuthorized('member') ||
|
|
||||||
(AuthService.isAuthorized('manager') && $scope.currentUser.id !== $scope.ctrl.member.id)) {
|
|
||||||
$rootScope.currentUser = user;
|
|
||||||
Auth._currentUser.group_id = user.group_id;
|
|
||||||
growl.success(_t('app.public.plans.your_group_was_successfully_changed'));
|
|
||||||
} else {
|
|
||||||
growl.success(_t('app.public.plans.the_user_s_group_was_successfully_changed'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, function (err) {
|
|
||||||
if (AuthService.isAuthorized('member') ||
|
|
||||||
(AuthService.isAuthorized('manager') && $scope.currentUser.id !== $scope.ctrl.member.id)) {
|
|
||||||
growl.error(_t('app.public.plans.an_error_prevented_your_group_from_being_changed'));
|
|
||||||
} else {
|
|
||||||
growl.error(_t('app.public.plans.an_error_prevented_to_change_the_user_s_group'));
|
|
||||||
}
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an enumerable meaninful string for the gender of the provider user
|
|
||||||
* @param user {Object} Database user record
|
|
||||||
* @return {string} 'male' or 'female'
|
|
||||||
*/
|
|
||||||
$scope.getGender = function (user) {
|
|
||||||
if (user && user.statistic_profile_attributes) {
|
|
||||||
if (user.statistic_profile_attributes.gender === 'true') { return 'male'; } else { return 'female'; }
|
|
||||||
} else { return 'other'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the provided date is in the future
|
* Test if the provided date is in the future
|
||||||
* @param dateTime {Date}
|
* @param dateTime {Date}
|
||||||
@ -199,7 +137,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if it is allowed the change the group of teh selected user
|
* Check if it is allowed the change the group of the selected user
|
||||||
*/
|
*/
|
||||||
$scope.isAllowedChangingGroup = function () {
|
$scope.isAllowedChangingGroup = function () {
|
||||||
return $scope.ctrl.member && !$scope.selectedPlan && !$scope.paid.plan;
|
return $scope.ctrl.member && !$scope.selectedPlan && !$scope.paid.plan;
|
||||||
@ -215,7 +153,6 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
if (!AuthService.isAuthorized('admin')) {
|
if (!AuthService.isAuthorized('admin')) {
|
||||||
$scope.ctrl.member = $scope.currentUser;
|
$scope.ctrl.member = $scope.currentUser;
|
||||||
$scope.paid.plan = $scope.currentUser.subscribed_plan;
|
$scope.paid.plan = $scope.currentUser.subscribed_plan;
|
||||||
$scope.group.id = $scope.currentUser.group_id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ export default class UserLib {
|
|||||||
* Check if the current user has privileged access for resources concerning the provided customer
|
* Check if the current user has privileged access for resources concerning the provided customer
|
||||||
*/
|
*/
|
||||||
isPrivileged = (customer: User): boolean => {
|
isPrivileged = (customer: User): boolean => {
|
||||||
if (this.user.role === 'admin') return true;
|
if (this.user?.role === 'admin') return true;
|
||||||
|
|
||||||
if (this.user.role === 'manager') {
|
if (this.user?.role === 'manager') {
|
||||||
return (this.user.id !== customer.id);
|
return (this.user?.id !== customer.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -134,6 +134,7 @@ export enum SettingName {
|
|||||||
SocialsLastfm = 'lastfm',
|
SocialsLastfm = 'lastfm',
|
||||||
SocialsFlickr = 'flickr',
|
SocialsFlickr = 'flickr',
|
||||||
MachinesModule = 'machines_module',
|
MachinesModule = 'machines_module',
|
||||||
|
UserChangeGroup = 'user_change_group',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SettingValue = string|boolean|number;
|
export type SettingValue = string|boolean|number;
|
||||||
|
@ -525,7 +525,6 @@ angular.module('application.router', ['ui.router'])
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise; }],
|
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise; }],
|
||||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
|
||||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['online_payment_module', 'payment_gateway', 'overlapping_categories']" }).$promise; }]
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['online_payment_module', 'payment_gateway', 'overlapping_categories']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1072,7 +1071,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
"'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," +
|
"'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," +
|
||||||
"'extended_prices_in_same_day', 'recaptcha_site_key', 'recaptcha_secret_key', 'user_validation_required', 'user_validation_required_machine', " +
|
"'extended_prices_in_same_day', 'recaptcha_site_key', 'recaptcha_secret_key', 'user_validation_required', 'user_validation_required_machine', " +
|
||||||
"'user_validation_required_training', 'user_validation_required_subscription', 'user_validation_required_space'," +
|
"'user_validation_required_training', 'user_validation_required_subscription', 'user_validation_required_space'," +
|
||||||
"'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list', 'machines_module']"
|
"'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list'," +
|
||||||
|
"'machines_module', 'user_change_group']"
|
||||||
}).$promise;
|
}).$promise;
|
||||||
}],
|
}],
|
||||||
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],
|
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
|
|
||||||
@import "modules/abuses";
|
@import "modules/abuses";
|
||||||
@import "modules/cookies";
|
@import "modules/cookies";
|
||||||
|
@import "modules/dashboard";
|
||||||
@import "modules/document-filters";
|
@import "modules/document-filters";
|
||||||
@import "modules/event-themes";
|
@import "modules/event-themes";
|
||||||
@import "modules/icalendar";
|
@import "modules/icalendar";
|
||||||
|
51
app/frontend/src/stylesheets/modules/dashboard.scss
Normal file
51
app/frontend/src/stylesheets/modules/dashboard.scss
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
.dashboard {
|
||||||
|
.dashboard-change-group {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
padding: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display,
|
||||||
|
.change-group-form {
|
||||||
|
padding: 10px 0 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display {
|
||||||
|
.current-group {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
border-color: #faebcc;
|
||||||
|
color: #8a6d3b;
|
||||||
|
}
|
||||||
|
.request-change-btn {
|
||||||
|
width: auto;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: var(--secondary);
|
||||||
|
border-color: var(--secondary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
.fab-button {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -480,6 +480,18 @@
|
|||||||
</boolean-setting>
|
</boolean-setting>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.change_group' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>
|
||||||
|
{{ 'app.admin.settings.change_group_info' }}
|
||||||
|
</p>
|
||||||
|
<div class="col-md-10 col-md-offset-1">
|
||||||
|
<boolean-setting name="user_change_group"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.allow_group_change">
|
||||||
|
</boolean-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row no-gutter wrapper">
|
<div class="row no-gutter wrapper dashboard">
|
||||||
<div class="col-sm-12 col-md-12 col-lg-3">
|
<div class="col-sm-12 col-md-12 col-lg-3">
|
||||||
<div class="widget panel b-a m m-t-lg">
|
<div class="widget panel b-a m m-t-lg">
|
||||||
<div class="panel-heading b-b small text-center">
|
<div class="panel-heading b-b small text-center">
|
||||||
@ -16,24 +16,12 @@
|
|||||||
<div class="text-xs" ng-show="user.last_sign_in_at"><i>{{ 'app.logged.dashboard.settings.last_activity_on_' | translate:{DATE:(user.last_sign_in_at | amDateFormat: 'LL')} }}</i></div>
|
<div class="text-xs" ng-show="user.last_sign_in_at"><i>{{ 'app.logged.dashboard.settings.last_activity_on_' | translate:{DATE:(user.last_sign_in_at | amDateFormat: 'LL')} }}</i></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="widget-content no-bg b-b auto wrapper">
|
<div class="widget-content no-bg b-b auto wrapper">
|
||||||
<div class="m-b-md">
|
<change-group user="user"
|
||||||
<h3 class="text-u-c" translate>{{ 'app.logged.dashboard.settings.group' }}</h3>
|
on-success="onGroupUpdateSuccess"
|
||||||
<div ng-show="!group.change">
|
on-error="onError"
|
||||||
<uib-alert type="warning">
|
class-name="'dashboard-change-group'"
|
||||||
<span class="text-black font-sbold">{{getUserGroup().name}}</span>
|
allow-change="isAllowedChangingGroup()">
|
||||||
</uib-alert>
|
</change-group>
|
||||||
<button class="btn text-black btn-warning-full btn-sm m-t-n-sm"
|
|
||||||
ng-click="group.change = !group.change"
|
|
||||||
ng-hide="user.subscribed_plan.name || user.role === 'admin'"
|
|
||||||
translate>
|
|
||||||
{{ 'app.logged.dashboard.settings.i_want_to_change_group' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div ng-show="group.change">
|
|
||||||
<select class="form-control" ng-options="g.id as g.name for g in groups" ng-model="userGroup"></select>
|
|
||||||
<button class="btn btn-success m-t" ng-click="selectGroup()">Changer mon groupe</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ng-show="$root.modules.plans">
|
<div ng-show="$root.modules.plans">
|
||||||
<h3 class="text-u-c" translate>{{ 'app.logged.dashboard.settings.subscription' }}</h3>
|
<h3 class="text-u-c" translate>{{ 'app.logged.dashboard.settings.subscription' }}</h3>
|
||||||
<div ng-show="user.subscribed_plan">
|
<div ng-show="user.subscribed_plan">
|
||||||
|
@ -144,7 +144,8 @@ class Setting < ApplicationRecord
|
|||||||
pinterest
|
pinterest
|
||||||
lastfm
|
lastfm
|
||||||
flickr
|
flickr
|
||||||
machines_module] }
|
machines_module
|
||||||
|
user_change_group] }
|
||||||
# WARNING: when adding a new key, you may also want to add it in:
|
# WARNING: when adding a new key, you may also want to add it in:
|
||||||
# - config/locales/en.yml#settings
|
# - config/locales/en.yml#settings
|
||||||
# - app/frontend/src/javascript/models/setting.ts#SettingName
|
# - app/frontend/src/javascript/models/setting.ts#SettingName
|
||||||
|
@ -40,7 +40,8 @@ class SettingPolicy < ApplicationPolicy
|
|||||||
recaptcha_site_key feature_tour_display disqus_shortname allowed_cad_extensions openlab_app_id openlab_default
|
recaptcha_site_key feature_tour_display disqus_shortname allowed_cad_extensions openlab_app_id openlab_default
|
||||||
online_payment_module stripe_public_key confirmation_required wallet_module trainings_module address_required
|
online_payment_module stripe_public_key confirmation_required wallet_module trainings_module address_required
|
||||||
payment_gateway payzen_endpoint payzen_public_key public_agenda_module renew_pack_threshold statistics_module
|
payment_gateway payzen_endpoint payzen_public_key public_agenda_module renew_pack_threshold statistics_module
|
||||||
pack_only_for_subscription overlapping_categories public_registrations socials_facebook socials_twitter socials_viadeo socials_linkedin socials_instagram socials_youtube socials_vimeo socials_dailymotion socials_github socials_echosciences socials_pinterest socials_lastfm socials_flickr]
|
pack_only_for_subscription overlapping_categories public_registrations facebook twitter viadeo linkedin instagram
|
||||||
|
youtube vimeo dailymotion github echosciences pinterest lastfm flickr machines_module user_change_group]
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -1408,6 +1408,10 @@ en:
|
|||||||
account_confirmation: "Account confirmation"
|
account_confirmation: "Account confirmation"
|
||||||
confirmation_required_info: "Optionally, you can force the users to confirm their email address before being able to access Fab-manager."
|
confirmation_required_info: "Optionally, you can force the users to confirm their email address before being able to access Fab-manager."
|
||||||
confirmation_is_required: "Confirmation required"
|
confirmation_is_required: "Confirmation required"
|
||||||
|
change_group: "Group change"
|
||||||
|
change_group_info: "After an user has created his account, you can restrict him from changing his group. In that case, only managers and administrators will be able to change the user's group."
|
||||||
|
allow_group_change: "Allow group change"
|
||||||
|
user_change_group: "users can change their group"
|
||||||
wallet_module: "wallet module"
|
wallet_module: "wallet module"
|
||||||
public_agenda_module: "public agenda module"
|
public_agenda_module: "public agenda module"
|
||||||
statistics_module: "statistics module"
|
statistics_module: "statistics module"
|
||||||
|
@ -582,3 +582,4 @@ en:
|
|||||||
lastfm: "lastfm"
|
lastfm: "lastfm"
|
||||||
flickr: "flickr"
|
flickr: "flickr"
|
||||||
machines_module: "Machines module"
|
machines_module: "Machines module"
|
||||||
|
user_change_group: "Allow users to change their group"
|
||||||
|
@ -905,6 +905,8 @@ Setting.set('pack_only_for_subscription', true) unless Setting.find_by(name: 'pa
|
|||||||
|
|
||||||
Setting.set('public_registrations', true) unless Setting.find_by(name: 'public_registrations').try(:value)
|
Setting.set('public_registrations', true) unless Setting.find_by(name: 'public_registrations').try(:value)
|
||||||
|
|
||||||
|
Setting.set('user_change_group', true) unless Setting.find_by(name: 'user_change_group').try(:value)
|
||||||
|
|
||||||
unless Setting.find_by(name: 'overlapping_categories').try(:value)
|
unless Setting.find_by(name: 'overlapping_categories').try(:value)
|
||||||
Setting.set('overlapping_categories', 'training_reservations,machine_reservations,space_reservations,events_reservations')
|
Setting.set('overlapping_categories', 'training_reservations,machine_reservations,space_reservations,events_reservations')
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user