mattermost-redux 10.8.0 → 10.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/action_types/admin.d.ts +8 -0
- package/lib/action_types/admin.js +8 -0
- package/lib/action_types/users.d.ts +1 -0
- package/lib/action_types/users.js +1 -0
- package/lib/actions/access_control.d.ts +14 -0
- package/lib/actions/access_control.js +142 -0
- package/lib/actions/admin.d.ts +2 -0
- package/lib/actions/admin.js +15 -0
- package/lib/actions/channels.d.ts +5 -2
- package/lib/actions/channels.js +38 -22
- package/lib/actions/posts.d.ts +1 -1
- package/lib/actions/posts.js +25 -7
- package/lib/constants/general.d.ts +1 -1
- package/lib/constants/general.js +1 -1
- package/lib/constants/permissions.d.ts +2 -0
- package/lib/constants/permissions.js +2 -0
- package/lib/constants/permissions_sysconsole.d.ts +4 -0
- package/lib/constants/permissions_sysconsole.js +6 -0
- package/lib/reducers/entities/admin.d.ts +3 -0
- package/lib/reducers/entities/admin.js +60 -0
- package/lib/reducers/entities/index.d.ts +2 -0
- package/lib/reducers/entities/users.js +18 -0
- package/lib/reducers/index.d.ts +2 -0
- package/lib/selectors/create_selector/index.js +2 -82
- package/lib/selectors/entities/access_control.d.ts +8 -0
- package/lib/selectors/entities/access_control.js +44 -0
- package/lib/selectors/entities/channel_banner.d.ts +1 -0
- package/lib/selectors/entities/channel_banner.js +11 -4
- package/lib/selectors/entities/report_a_problem.d.ts +3 -0
- package/lib/selectors/entities/report_a_problem.js +46 -0
- package/lib/store/initial_state.js +2 -0
- package/lib/utils/browser_info.d.ts +5 -0
- package/lib/utils/browser_info.js +96 -0
- package/package.json +3 -3
|
@@ -47,5 +47,13 @@ declare const _default: {
|
|
|
47
47
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_TEAMS_FAILURE: "REMOVE_DATA_RETENTION_CUSTOM_POLICY_TEAMS_FAILURE";
|
|
48
48
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_SUCCESS: "REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_SUCCESS";
|
|
49
49
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_FAILURE: "REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_FAILURE";
|
|
50
|
+
RECEIVED_ACCESS_CONTROL_POLICIES: "RECEIVED_ACCESS_CONTROL_POLICIES";
|
|
51
|
+
RECEIVED_ACCESS_CONTROL_POLICY: "RECEIVED_ACCESS_CONTROL_POLICY";
|
|
52
|
+
CREATE_ACCESS_CONTROL_POLICY_SUCCESS: "CREATE_ACCESS_CONTROL_POLICY_SUCCESS";
|
|
53
|
+
DELETE_ACCESS_CONTROL_POLICY_SUCCESS: "DELETE_ACCESS_CONTROL_POLICY_SUCCESS";
|
|
54
|
+
RECEIVED_ACCESS_CONTROL_CHILD_POLICIES: "RECEIVED_ACCESS_CONTROL_CHILD_POLICIES";
|
|
55
|
+
RECEIVED_ACCESS_CONTROL_POLICIES_SEARCH: "RECEIVED_ACCESS_CONTROL_POLICIES_SEARCH";
|
|
56
|
+
ASSIGN_CHANNELS_TO_ACCESS_CONTROL_POLICY_SUCCESS: "ASSIGN_CHANNELS_TO_ACCESS_CONTROL_POLICY_SUCCESS";
|
|
57
|
+
UNASSIGN_CHANNELS_FROM_ACCESS_CONTROL_POLICY_SUCCESS: "UNASSIGN_CHANNELS_FROM_ACCESS_CONTROL_POLICY_SUCCESS";
|
|
50
58
|
};
|
|
51
59
|
export default _default;
|
|
@@ -55,4 +55,12 @@ exports.default = (0, key_mirror_1.default)({
|
|
|
55
55
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_TEAMS_FAILURE: null,
|
|
56
56
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_SUCCESS: null,
|
|
57
57
|
REMOVE_DATA_RETENTION_CUSTOM_POLICY_CHANNELS_FAILURE: null,
|
|
58
|
+
RECEIVED_ACCESS_CONTROL_POLICIES: null,
|
|
59
|
+
RECEIVED_ACCESS_CONTROL_POLICY: null,
|
|
60
|
+
CREATE_ACCESS_CONTROL_POLICY_SUCCESS: null,
|
|
61
|
+
DELETE_ACCESS_CONTROL_POLICY_SUCCESS: null,
|
|
62
|
+
RECEIVED_ACCESS_CONTROL_CHILD_POLICIES: null,
|
|
63
|
+
RECEIVED_ACCESS_CONTROL_POLICIES_SEARCH: null,
|
|
64
|
+
ASSIGN_CHANNELS_TO_ACCESS_CONTROL_POLICY_SUCCESS: null,
|
|
65
|
+
UNASSIGN_CHANNELS_FROM_ACCESS_CONTROL_POLICY_SUCCESS: null,
|
|
58
66
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AccessControlPoliciesResult, AccessControlPolicy, AccessControlTestResult } from '@mattermost/types/access_control';
|
|
2
|
+
import type { ChannelSearchOpts, ChannelsWithTotalCount } from '@mattermost/types/channels';
|
|
3
|
+
import type { ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
4
|
+
export declare function getAccessControlPolicy(id: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
5
|
+
export declare function createAccessControlPolicy(policy: AccessControlPolicy): ActionFuncAsync<AccessControlPolicy>;
|
|
6
|
+
export declare function deleteAccessControlPolicy(id: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
7
|
+
export declare function searchAccessControlPolicies(term: string, type: string, after: string, limit: number): ActionFuncAsync<AccessControlPoliciesResult>;
|
|
8
|
+
export declare function searchAccessControlPolicyChannels(id: string, term: string, opts: ChannelSearchOpts): ActionFuncAsync<ChannelsWithTotalCount>;
|
|
9
|
+
export declare function assignChannelsToAccessControlPolicy(policyId: string, channelIds: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
10
|
+
export declare function unassignChannelsFromAccessControlPolicy(policyId: string, channelIds: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
11
|
+
export declare function getAccessControlFields(after: string, limit: number): ActionFuncAsync<import("@mattermost/types/properties").UserPropertyField[], import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
12
|
+
export declare function updateAccessControlPolicyActive(policyId: string, active: boolean): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
13
|
+
export declare function searchUsersForExpression(expression: string, term: string, after: string, limit: number): ActionFuncAsync<AccessControlTestResult>;
|
|
14
|
+
export declare function getVisualAST(expression: string): ActionFuncAsync<import("@mattermost/types/access_control").AccessControlVisualAST, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getAccessControlPolicy = getAccessControlPolicy;
|
|
6
|
+
exports.createAccessControlPolicy = createAccessControlPolicy;
|
|
7
|
+
exports.deleteAccessControlPolicy = deleteAccessControlPolicy;
|
|
8
|
+
exports.searchAccessControlPolicies = searchAccessControlPolicies;
|
|
9
|
+
exports.searchAccessControlPolicyChannels = searchAccessControlPolicyChannels;
|
|
10
|
+
exports.assignChannelsToAccessControlPolicy = assignChannelsToAccessControlPolicy;
|
|
11
|
+
exports.unassignChannelsFromAccessControlPolicy = unassignChannelsFromAccessControlPolicy;
|
|
12
|
+
exports.getAccessControlFields = getAccessControlFields;
|
|
13
|
+
exports.updateAccessControlPolicyActive = updateAccessControlPolicyActive;
|
|
14
|
+
exports.searchUsersForExpression = searchUsersForExpression;
|
|
15
|
+
exports.getVisualAST = getVisualAST;
|
|
16
|
+
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
17
|
+
const action_types_1 = require("mattermost-redux/action_types");
|
|
18
|
+
const client_1 = require("mattermost-redux/client");
|
|
19
|
+
const helpers_1 = require("./helpers");
|
|
20
|
+
function getAccessControlPolicy(id) {
|
|
21
|
+
return (0, helpers_1.bindClientFunc)({
|
|
22
|
+
clientFunc: client_1.Client4.getAccessControlPolicy,
|
|
23
|
+
onSuccess: [action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICY],
|
|
24
|
+
params: [
|
|
25
|
+
id,
|
|
26
|
+
],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function createAccessControlPolicy(policy) {
|
|
30
|
+
return async (dispatch, getState) => {
|
|
31
|
+
let data;
|
|
32
|
+
try {
|
|
33
|
+
data = await client_1.Client4.updateOrCreateAccessControlPolicy(policy);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
37
|
+
return { error };
|
|
38
|
+
}
|
|
39
|
+
dispatch({ type: action_types_1.AdminTypes.CREATE_ACCESS_CONTROL_POLICY_SUCCESS, data });
|
|
40
|
+
return { data };
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function deleteAccessControlPolicy(id) {
|
|
44
|
+
return (0, helpers_1.bindClientFunc)({
|
|
45
|
+
clientFunc: client_1.Client4.deleteAccessControlPolicy,
|
|
46
|
+
onSuccess: [action_types_1.AdminTypes.DELETE_ACCESS_CONTROL_POLICY_SUCCESS],
|
|
47
|
+
params: [
|
|
48
|
+
id,
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function searchAccessControlPolicies(term, type, after, limit) {
|
|
53
|
+
return async (dispatch, getState) => {
|
|
54
|
+
let data;
|
|
55
|
+
try {
|
|
56
|
+
data = await client_1.Client4.searchAccessControlPolicies(term, type, after, limit);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
60
|
+
return { error };
|
|
61
|
+
}
|
|
62
|
+
dispatch({ type: action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICIES_SEARCH, data: data.policies });
|
|
63
|
+
return { data };
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function searchAccessControlPolicyChannels(id, term, opts) {
|
|
67
|
+
return async (dispatch, getState) => {
|
|
68
|
+
let data;
|
|
69
|
+
try {
|
|
70
|
+
data = await client_1.Client4.searchChildAccessControlPolicyChannels(id, term, opts);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
74
|
+
return { error };
|
|
75
|
+
}
|
|
76
|
+
const childs = {};
|
|
77
|
+
childs[id] = data.channels.map((channel) => channel.id);
|
|
78
|
+
dispatch((0, redux_batched_actions_1.batchActions)([
|
|
79
|
+
{ type: action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_CHILD_POLICIES, data: childs },
|
|
80
|
+
{ type: action_types_1.ChannelTypes.RECEIVED_CHANNELS, data: data.channels },
|
|
81
|
+
]));
|
|
82
|
+
return { data };
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function assignChannelsToAccessControlPolicy(policyId, channelIds) {
|
|
86
|
+
return (0, helpers_1.bindClientFunc)({
|
|
87
|
+
clientFunc: client_1.Client4.assignChannelsToAccessControlPolicy,
|
|
88
|
+
onSuccess: [action_types_1.AdminTypes.ASSIGN_CHANNELS_TO_ACCESS_CONTROL_POLICY_SUCCESS],
|
|
89
|
+
params: [
|
|
90
|
+
policyId,
|
|
91
|
+
channelIds,
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function unassignChannelsFromAccessControlPolicy(policyId, channelIds) {
|
|
96
|
+
return (0, helpers_1.bindClientFunc)({
|
|
97
|
+
clientFunc: client_1.Client4.unassignChannelsFromAccessControlPolicy,
|
|
98
|
+
onSuccess: [action_types_1.AdminTypes.UNASSIGN_CHANNELS_FROM_ACCESS_CONTROL_POLICY_SUCCESS],
|
|
99
|
+
params: [
|
|
100
|
+
policyId,
|
|
101
|
+
channelIds,
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function getAccessControlFields(after, limit) {
|
|
106
|
+
return (0, helpers_1.bindClientFunc)({
|
|
107
|
+
clientFunc: client_1.Client4.getAccessControlFields,
|
|
108
|
+
params: [
|
|
109
|
+
after,
|
|
110
|
+
limit,
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function updateAccessControlPolicyActive(policyId, active) {
|
|
115
|
+
return (0, helpers_1.bindClientFunc)({
|
|
116
|
+
clientFunc: client_1.Client4.updateAccessControlPolicyActive,
|
|
117
|
+
params: [
|
|
118
|
+
policyId,
|
|
119
|
+
active,
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function searchUsersForExpression(expression, term, after, limit) {
|
|
124
|
+
return async (dispatch, getState) => {
|
|
125
|
+
let data;
|
|
126
|
+
try {
|
|
127
|
+
data = await client_1.Client4.testAccessControlExpression(expression, term, after, limit);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
131
|
+
return { error };
|
|
132
|
+
}
|
|
133
|
+
dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES, data: data.users });
|
|
134
|
+
return { data };
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function getVisualAST(expression) {
|
|
138
|
+
return (0, helpers_1.bindClientFunc)({
|
|
139
|
+
clientFunc: client_1.Client4.expressionToVisualFormat,
|
|
140
|
+
params: [expression],
|
|
141
|
+
});
|
|
142
|
+
}
|
package/lib/actions/admin.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export declare function uploadPrivateSamlCertificate(fileData: File): ActionFunc
|
|
|
40
40
|
export declare function uploadPublicLdapCertificate(fileData: File): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
41
41
|
export declare function uploadPrivateLdapCertificate(fileData: File): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
42
42
|
export declare function uploadIdpSamlCertificate(fileData: File): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
43
|
+
export declare function uploadAuditCertificate(fileData: File): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
44
|
+
export declare function removeAuditCertificate(): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
43
45
|
export declare function removePublicSamlCertificate(): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
44
46
|
export declare function removePrivateSamlCertificate(): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
45
47
|
export declare function removePublicLdapCertificate(): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
package/lib/actions/admin.js
CHANGED
|
@@ -31,6 +31,8 @@ exports.uploadPrivateSamlCertificate = uploadPrivateSamlCertificate;
|
|
|
31
31
|
exports.uploadPublicLdapCertificate = uploadPublicLdapCertificate;
|
|
32
32
|
exports.uploadPrivateLdapCertificate = uploadPrivateLdapCertificate;
|
|
33
33
|
exports.uploadIdpSamlCertificate = uploadIdpSamlCertificate;
|
|
34
|
+
exports.uploadAuditCertificate = uploadAuditCertificate;
|
|
35
|
+
exports.removeAuditCertificate = removeAuditCertificate;
|
|
34
36
|
exports.removePublicSamlCertificate = removePublicSamlCertificate;
|
|
35
37
|
exports.removePrivateSamlCertificate = removePrivateSamlCertificate;
|
|
36
38
|
exports.removePublicLdapCertificate = removePublicLdapCertificate;
|
|
@@ -334,6 +336,19 @@ function uploadIdpSamlCertificate(fileData) {
|
|
|
334
336
|
],
|
|
335
337
|
});
|
|
336
338
|
}
|
|
339
|
+
function uploadAuditCertificate(fileData) {
|
|
340
|
+
return (0, helpers_1.bindClientFunc)({
|
|
341
|
+
clientFunc: client_1.Client4.uploadAuditLogCertificate,
|
|
342
|
+
params: [
|
|
343
|
+
fileData,
|
|
344
|
+
],
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function removeAuditCertificate() {
|
|
348
|
+
return (0, helpers_1.bindClientFunc)({
|
|
349
|
+
clientFunc: client_1.Client4.removeAuditLogCertificate,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
337
352
|
function removePublicSamlCertificate() {
|
|
338
353
|
return (0, helpers_1.bindClientFunc)({
|
|
339
354
|
clientFunc: client_1.Client4.deletePublicSamlCertificate,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyAction } from 'redux';
|
|
2
|
+
import type { AccessControlAttributes } from '@mattermost/types/access_control';
|
|
2
3
|
import type { Channel, ChannelNotifyProps, ChannelMembership, ChannelModerationPatch, ChannelsWithTotalCount, ChannelSearchOpts, ServerChannel, ChannelStats, ChannelWithTeamData } from '@mattermost/types/channels';
|
|
3
4
|
import type { OptsSignalExt } from '@mattermost/types/client4';
|
|
4
5
|
import type { GetStateFunc, ActionFunc, ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
@@ -40,8 +41,8 @@ export declare function unsetActiveChannelOnServer(): ActionFuncAsync;
|
|
|
40
41
|
export declare function readMultipleChannels(channelIds: string[]): ActionFuncAsync;
|
|
41
42
|
export declare function getChannels(teamId: string, page?: number, perPage?: number): ActionFuncAsync<Channel[]>;
|
|
42
43
|
export declare function getArchivedChannels(teamId: string, page?: number, perPage?: number): ActionFuncAsync<Channel[]>;
|
|
43
|
-
export declare function getAllChannelsWithCount(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean, excludePolicyConstrained?: boolean): ActionFuncAsync<ChannelsWithTotalCount>;
|
|
44
|
-
export declare function getAllChannels(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, excludePolicyConstrained?: boolean): ActionFuncAsync<ChannelWithTeamData[]>;
|
|
44
|
+
export declare function getAllChannelsWithCount(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean, excludePolicyConstrained?: boolean, accessControlPolicyEnforced?: boolean, excludeAccessControlPolicyEnforced?: boolean): ActionFuncAsync<ChannelsWithTotalCount>;
|
|
45
|
+
export declare function getAllChannels(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, excludePolicyConstrained?: boolean, excludeAccessControlPolicyEnforced?: boolean, accessControlPolicyEnforced?: boolean): ActionFuncAsync<ChannelWithTeamData[]>;
|
|
45
46
|
export declare function autocompleteChannels(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
|
46
47
|
export declare function autocompleteChannelsForSearch(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
|
47
48
|
export declare function searchChannels(teamId: string, term: string, archived?: boolean): ActionFuncAsync<Channel[]>;
|
|
@@ -91,6 +92,7 @@ export declare function getChannelMemberCountsByGroup(channelId: string): Action
|
|
|
91
92
|
memberCounts: import("@mattermost/types/channels").ChannelMemberCountsByGroup;
|
|
92
93
|
}, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
93
94
|
export declare function fetchMissingChannels(channelIDs: string[]): ActionFuncAsync<Array<Channel['id']>>;
|
|
95
|
+
export declare function getChannelAccessControlAttributes(channelId: string): ActionFuncAsync<AccessControlAttributes>;
|
|
94
96
|
declare const _default: {
|
|
95
97
|
selectChannel: typeof selectChannel;
|
|
96
98
|
createChannel: typeof createChannel;
|
|
@@ -120,5 +122,6 @@ declare const _default: {
|
|
|
120
122
|
membersMinusGroupMembers: typeof membersMinusGroupMembers;
|
|
121
123
|
getChannelModerations: typeof getChannelModerations;
|
|
122
124
|
getChannelMemberCountsByGroup: typeof getChannelMemberCountsByGroup;
|
|
125
|
+
getChannelAccessControlAttributes: typeof getChannelAccessControlAttributes;
|
|
123
126
|
};
|
|
124
127
|
export default _default;
|
package/lib/actions/channels.js
CHANGED
|
@@ -58,6 +58,7 @@ exports.getChannelModerations = getChannelModerations;
|
|
|
58
58
|
exports.patchChannelModerations = patchChannelModerations;
|
|
59
59
|
exports.getChannelMemberCountsByGroup = getChannelMemberCountsByGroup;
|
|
60
60
|
exports.fetchMissingChannels = fetchMissingChannels;
|
|
61
|
+
exports.getChannelAccessControlAttributes = getChannelAccessControlAttributes;
|
|
61
62
|
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
62
63
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
63
64
|
const client_1 = require("mattermost-redux/client");
|
|
@@ -411,8 +412,8 @@ function getChannelTimezones(channelId) {
|
|
|
411
412
|
}
|
|
412
413
|
function fetchChannelsAndMembers(teamId) {
|
|
413
414
|
return async (dispatch, getState) => {
|
|
414
|
-
let channels;
|
|
415
|
-
let channelMembers;
|
|
415
|
+
let channels = [];
|
|
416
|
+
let channelMembers = [];
|
|
416
417
|
try {
|
|
417
418
|
[channels, channelMembers] = await Promise.all([
|
|
418
419
|
client_1.Client4.getMyChannels(teamId),
|
|
@@ -451,32 +452,32 @@ function fetchAllMyChannelMembers() {
|
|
|
451
452
|
return async (dispatch, getState) => {
|
|
452
453
|
const state = getState();
|
|
453
454
|
const { currentUserId } = state.entities.users;
|
|
454
|
-
let
|
|
455
|
-
let hasMoreMembers = true;
|
|
456
|
-
let page = 0;
|
|
455
|
+
let channelMembers = [];
|
|
457
456
|
try {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const data = await client_1.Client4.getAllChannelsMembers(currentUserId, page, 200);
|
|
462
|
-
channelsMembers = [...channelsMembers, ...data];
|
|
463
|
-
if (data.length < 200) {
|
|
464
|
-
hasMoreMembers = false;
|
|
465
|
-
}
|
|
466
|
-
page++;
|
|
467
|
-
}
|
|
457
|
+
// The server exposes a streaming API if page is set to -1
|
|
458
|
+
// We don't need to paginate through the responses, and thefore pageSize doesn't matter
|
|
459
|
+
channelMembers = await client_1.Client4.getAllChannelsMembers(currentUserId, -1);
|
|
468
460
|
}
|
|
469
461
|
catch (error) {
|
|
470
462
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
471
463
|
dispatch((0, errors_1.logError)(error));
|
|
472
464
|
return { error };
|
|
473
465
|
}
|
|
466
|
+
const roles = new Set();
|
|
467
|
+
for (const member of channelMembers) {
|
|
468
|
+
for (const role of member.roles.split(' ')) {
|
|
469
|
+
roles.add(role);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (roles.size > 0) {
|
|
473
|
+
dispatch((0, roles_1.loadRolesIfNeeded)(roles));
|
|
474
|
+
}
|
|
474
475
|
dispatch({
|
|
475
476
|
type: action_types_1.ChannelTypes.RECEIVED_MY_CHANNEL_MEMBERS,
|
|
476
|
-
data:
|
|
477
|
+
data: channelMembers,
|
|
477
478
|
currentUserId,
|
|
478
479
|
});
|
|
479
|
-
return { data:
|
|
480
|
+
return { data: channelMembers };
|
|
480
481
|
};
|
|
481
482
|
}
|
|
482
483
|
function fetchAllMyTeamsChannels() {
|
|
@@ -491,7 +492,7 @@ function fetchAllMyTeamsChannels() {
|
|
|
491
492
|
return { error };
|
|
492
493
|
}
|
|
493
494
|
dispatch({
|
|
494
|
-
type: action_types_1.ChannelTypes.
|
|
495
|
+
type: action_types_1.ChannelTypes.RECEIVED_CHANNELS,
|
|
495
496
|
data: channels,
|
|
496
497
|
});
|
|
497
498
|
return { data: channels };
|
|
@@ -735,12 +736,12 @@ function getArchivedChannels(teamId, page = 0, perPage = constants_1.General.CHA
|
|
|
735
736
|
return { data: channels };
|
|
736
737
|
};
|
|
737
738
|
}
|
|
738
|
-
function getAllChannelsWithCount(page = 0, perPage = constants_1.General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup = '', excludeDefaultChannels = false, includeDeleted = false, excludePolicyConstrained = false) {
|
|
739
|
+
function getAllChannelsWithCount(page = 0, perPage = constants_1.General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup = '', excludeDefaultChannels = false, includeDeleted = false, excludePolicyConstrained = false, accessControlPolicyEnforced = false, excludeAccessControlPolicyEnforced = false) {
|
|
739
740
|
return async (dispatch, getState) => {
|
|
740
741
|
dispatch({ type: action_types_1.ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null });
|
|
741
742
|
let payload;
|
|
742
743
|
try {
|
|
743
|
-
payload = await client_1.Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels, true, includeDeleted, excludePolicyConstrained);
|
|
744
|
+
payload = await client_1.Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels, true, includeDeleted, excludePolicyConstrained, accessControlPolicyEnforced, excludeAccessControlPolicyEnforced);
|
|
744
745
|
}
|
|
745
746
|
catch (error) {
|
|
746
747
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
@@ -764,12 +765,12 @@ function getAllChannelsWithCount(page = 0, perPage = constants_1.General.CHANNEL
|
|
|
764
765
|
return { data: payload };
|
|
765
766
|
};
|
|
766
767
|
}
|
|
767
|
-
function getAllChannels(page = 0, perPage = constants_1.General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup = '', excludeDefaultChannels = false, excludePolicyConstrained = false) {
|
|
768
|
+
function getAllChannels(page = 0, perPage = constants_1.General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup = '', excludeDefaultChannels = false, excludePolicyConstrained = false, excludeAccessControlPolicyEnforced = false, accessControlPolicyEnforced = false) {
|
|
768
769
|
return async (dispatch, getState) => {
|
|
769
770
|
dispatch({ type: action_types_1.ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null });
|
|
770
771
|
let channels;
|
|
771
772
|
try {
|
|
772
|
-
channels = await client_1.Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels, false, false, excludePolicyConstrained);
|
|
773
|
+
channels = await client_1.Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels, false, false, excludePolicyConstrained, accessControlPolicyEnforced, excludeAccessControlPolicyEnforced);
|
|
773
774
|
}
|
|
774
775
|
catch (error) {
|
|
775
776
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
@@ -1317,6 +1318,20 @@ function fetchMissingChannels(channelIDs) {
|
|
|
1317
1318
|
};
|
|
1318
1319
|
};
|
|
1319
1320
|
}
|
|
1321
|
+
function getChannelAccessControlAttributes(channelId) {
|
|
1322
|
+
return async (dispatch, getState) => {
|
|
1323
|
+
let data;
|
|
1324
|
+
try {
|
|
1325
|
+
data = await client_1.Client4.getChannelAccessControlAttributes(channelId);
|
|
1326
|
+
}
|
|
1327
|
+
catch (error) {
|
|
1328
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
1329
|
+
dispatch((0, errors_1.logError)(error));
|
|
1330
|
+
return { error };
|
|
1331
|
+
}
|
|
1332
|
+
return { data };
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1320
1335
|
exports.default = {
|
|
1321
1336
|
selectChannel,
|
|
1322
1337
|
createChannel,
|
|
@@ -1346,4 +1361,5 @@ exports.default = {
|
|
|
1346
1361
|
membersMinusGroupMembers,
|
|
1347
1362
|
getChannelModerations,
|
|
1348
1363
|
getChannelMemberCountsByGroup,
|
|
1364
|
+
getChannelAccessControlAttributes,
|
|
1349
1365
|
};
|
package/lib/actions/posts.d.ts
CHANGED
|
@@ -97,7 +97,7 @@ export declare function addReaction(postId: string, emojiName: string): ActionFu
|
|
|
97
97
|
export declare function removeReaction(postId: string, emojiName: string): ActionFuncAsync<SubmitReactionReturnType>;
|
|
98
98
|
export declare function getCustomEmojiForReaction(name: string): ActionFuncAsync;
|
|
99
99
|
export declare function flagPost(postId: string): ActionFuncAsync;
|
|
100
|
-
export declare function getPostThread(rootId: string, fetchThreads?: boolean): ActionFuncAsync<PostList>;
|
|
100
|
+
export declare function getPostThread(rootId: string, fetchThreads?: boolean, lastUpdateAt?: number): ActionFuncAsync<PostList>;
|
|
101
101
|
export declare function getNewestPostThread(rootId: string): ActionFuncAsync;
|
|
102
102
|
export declare function getPosts(channelId: string, page?: number, perPage?: number, fetchThreads?: boolean, collapsedThreadsExtended?: boolean): ActionFuncAsync<PostList>;
|
|
103
103
|
export declare function getPostsUnread(channelId: string, fetchThreads?: boolean, collapsedThreadsExtended?: boolean): ActionFuncAsync<PostList>;
|
package/lib/actions/posts.js
CHANGED
|
@@ -587,23 +587,41 @@ async function getPaginatedPostThread(rootId, options, prevList) {
|
|
|
587
587
|
if (result.has_next) {
|
|
588
588
|
const [nextPostId] = list.order.slice(-1);
|
|
589
589
|
const nextPostPointer = list.posts[nextPostId];
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
590
|
+
let newOptions;
|
|
591
|
+
if (options.updatesOnly) {
|
|
592
|
+
newOptions = {
|
|
593
|
+
...options,
|
|
594
|
+
fromUpdateAt: nextPostPointer.update_at,
|
|
595
|
+
fromPost: nextPostId,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
newOptions = {
|
|
600
|
+
...options,
|
|
601
|
+
fromCreateAt: nextPostPointer.create_at,
|
|
602
|
+
fromPost: nextPostId,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
595
605
|
return getPaginatedPostThread(rootId, newOptions, list);
|
|
596
606
|
}
|
|
597
607
|
return list;
|
|
598
608
|
}
|
|
599
|
-
function getPostThread(rootId, fetchThreads = true) {
|
|
609
|
+
function getPostThread(rootId, fetchThreads = true, lastUpdateAt = 0) {
|
|
600
610
|
return async (dispatch, getState) => {
|
|
601
611
|
const state = getState();
|
|
602
612
|
const collapsedThreadsEnabled = (0, preferences_2.isCollapsedThreadsEnabled)(state);
|
|
603
613
|
const enabledUserStatuses = (0, common_1.getIsUserStatusesConfigEnabled)(state);
|
|
604
614
|
let posts;
|
|
615
|
+
const options = {
|
|
616
|
+
fetchThreads,
|
|
617
|
+
collapsedThreads: collapsedThreadsEnabled,
|
|
618
|
+
};
|
|
619
|
+
if (lastUpdateAt !== 0) {
|
|
620
|
+
options.updatesOnly = true;
|
|
621
|
+
options.fromUpdateAt = lastUpdateAt;
|
|
622
|
+
}
|
|
605
623
|
try {
|
|
606
|
-
posts = await getPaginatedPostThread(rootId,
|
|
624
|
+
posts = await getPaginatedPostThread(rootId, options);
|
|
607
625
|
}
|
|
608
626
|
catch (error) {
|
|
609
627
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
package/lib/constants/general.js
CHANGED
|
@@ -27,6 +27,8 @@ declare const values: {
|
|
|
27
27
|
DELETE_PUBLIC_CHANNEL: string;
|
|
28
28
|
CONVERT_PUBLIC_CHANNEL_TO_PRIVATE: string;
|
|
29
29
|
CONVERT_PRIVATE_CHANNEL_TO_PUBLIC: string;
|
|
30
|
+
MANAGE_PUBLIC_CHANNEL_BANNER: string;
|
|
31
|
+
MANAGE_PRIVATE_CHANNEL_BANNER: string;
|
|
30
32
|
DELETE_PRIVATE_CHANNEL: string;
|
|
31
33
|
EDIT_OTHER_USERS: string;
|
|
32
34
|
READ_CHANNEL: string;
|
|
@@ -31,6 +31,8 @@ const values = {
|
|
|
31
31
|
DELETE_PUBLIC_CHANNEL: 'delete_public_channel',
|
|
32
32
|
CONVERT_PUBLIC_CHANNEL_TO_PRIVATE: 'convert_public_channel_to_private',
|
|
33
33
|
CONVERT_PRIVATE_CHANNEL_TO_PUBLIC: 'convert_private_channel_to_public',
|
|
34
|
+
MANAGE_PUBLIC_CHANNEL_BANNER: 'manage_public_channel_banner',
|
|
35
|
+
MANAGE_PRIVATE_CHANNEL_BANNER: 'manage_private_channel_banner',
|
|
34
36
|
DELETE_PRIVATE_CHANNEL: 'delete_private_channel',
|
|
35
37
|
EDIT_OTHER_USERS: 'edit_other_users',
|
|
36
38
|
READ_CHANNEL: 'read_channel',
|
|
@@ -24,6 +24,10 @@ exports.RESOURCE_KEYS = {
|
|
|
24
24
|
PERMISSIONS: 'user_management.permissions',
|
|
25
25
|
SYSTEM_ROLES: 'user_management.system_roles',
|
|
26
26
|
},
|
|
27
|
+
SYSTEM_ATTRIBUTES: {
|
|
28
|
+
USER_ATTRIBUTES: 'system_attributes.user_attributes',
|
|
29
|
+
ATTRIBUTE_BASED_ACCESS_CONTROL: 'system_attributes.attribute_based_access_control',
|
|
30
|
+
},
|
|
27
31
|
AUTHENTICATION: {
|
|
28
32
|
SIGNUP: 'authentication.signup',
|
|
29
33
|
EMAIL: 'authentication.email',
|
|
@@ -96,6 +100,8 @@ exports.ResourceToSysConsolePermissionsTable = {
|
|
|
96
100
|
[exports.RESOURCE_KEYS.USER_MANAGEMENT.CHANNELS]: [permissions_1.default.SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS, permissions_1.default.SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS],
|
|
97
101
|
[exports.RESOURCE_KEYS.USER_MANAGEMENT.PERMISSIONS]: [permissions_1.default.SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS, permissions_1.default.SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS],
|
|
98
102
|
[exports.RESOURCE_KEYS.USER_MANAGEMENT.SYSTEM_ROLES]: [permissions_1.default.SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES, permissions_1.default.SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES],
|
|
103
|
+
[exports.RESOURCE_KEYS.SYSTEM_ATTRIBUTES.USER_ATTRIBUTES]: [permissions_1.default.SYSCONSOLE_READ_USERMANAGEMENT_USERS, permissions_1.default.SYSCONSOLE_WRITE_USERMANAGEMENT_USERS],
|
|
104
|
+
[exports.RESOURCE_KEYS.SYSTEM_ATTRIBUTES.ATTRIBUTE_BASED_ACCESS_CONTROL]: [permissions_1.default.SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES, permissions_1.default.SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES],
|
|
99
105
|
[exports.RESOURCE_KEYS.SITE.CUSTOMIZATION]: [permissions_1.default.SYSCONSOLE_READ_SITE_CUSTOMIZATION, permissions_1.default.SYSCONSOLE_WRITE_SITE_CUSTOMIZATION],
|
|
100
106
|
[exports.RESOURCE_KEYS.SITE.LOCALIZATION]: [permissions_1.default.SYSCONSOLE_READ_SITE_LOCALIZATION, permissions_1.default.SYSCONSOLE_WRITE_SITE_LOCALIZATION],
|
|
101
107
|
[exports.RESOURCE_KEYS.SITE.USERS_AND_TEAMS]: [permissions_1.default.SYSCONSOLE_READ_SITE_USERS_AND_TEAMS, permissions_1.default.SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AccessControlPolicy } from '@mattermost/types/access_control';
|
|
1
2
|
import type { AnalyticsRow, AnalyticsState } from '@mattermost/types/admin';
|
|
2
3
|
import type { Audit } from '@mattermost/types/audits';
|
|
3
4
|
import type { Compliance } from '@mattermost/types/compliance';
|
|
@@ -27,5 +28,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
27
28
|
dataRetentionCustomPolicies: IDMappedObjects<DataRetentionCustomPolicy>;
|
|
28
29
|
dataRetentionCustomPoliciesCount: any;
|
|
29
30
|
prevTrialLicense: any;
|
|
31
|
+
accessControlPolicies: IDMappedObjects<AccessControlPolicy>;
|
|
32
|
+
channelsForAccessControlPolicy: any;
|
|
30
33
|
}>, import("redux").AnyAction>;
|
|
31
34
|
export default _default;
|
|
@@ -572,6 +572,62 @@ function dataRetentionCustomPoliciesCount(state = 0, action) {
|
|
|
572
572
|
return state;
|
|
573
573
|
}
|
|
574
574
|
}
|
|
575
|
+
function accessControlPolicies(state = {}, action) {
|
|
576
|
+
switch (action.type) {
|
|
577
|
+
case action_types_1.AdminTypes.CREATE_ACCESS_CONTROL_POLICY_SUCCESS:
|
|
578
|
+
case action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICY:
|
|
579
|
+
return {
|
|
580
|
+
...state,
|
|
581
|
+
[action.data.id]: action.data,
|
|
582
|
+
};
|
|
583
|
+
case action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICIES: {
|
|
584
|
+
const nextState = {};
|
|
585
|
+
for (const policy of action.data) {
|
|
586
|
+
nextState[policy.id] = policy;
|
|
587
|
+
}
|
|
588
|
+
return nextState;
|
|
589
|
+
}
|
|
590
|
+
case action_types_1.AdminTypes.DELETE_ACCESS_CONTROL_POLICY_SUCCESS: {
|
|
591
|
+
const nextState = { ...state };
|
|
592
|
+
Reflect.deleteProperty(nextState, action.data.id);
|
|
593
|
+
return nextState;
|
|
594
|
+
}
|
|
595
|
+
case action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICIES_SEARCH: {
|
|
596
|
+
const nextState = { ...state };
|
|
597
|
+
for (const policy of action.data) {
|
|
598
|
+
nextState[policy.id] = policy;
|
|
599
|
+
}
|
|
600
|
+
return nextState;
|
|
601
|
+
}
|
|
602
|
+
case action_types_1.UserTypes.LOGOUT_SUCCESS:
|
|
603
|
+
return {};
|
|
604
|
+
default:
|
|
605
|
+
return state;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function channelsForAccessControlPolicy(state = {}, action) {
|
|
609
|
+
switch (action.type) {
|
|
610
|
+
case action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_CHILD_POLICIES:
|
|
611
|
+
if (action.data) {
|
|
612
|
+
return { ...state, ...action.data };
|
|
613
|
+
}
|
|
614
|
+
return state;
|
|
615
|
+
case action_types_1.AdminTypes.ASSIGN_CHANNELS_TO_ACCESS_CONTROL_POLICY_SUCCESS:
|
|
616
|
+
return {
|
|
617
|
+
...state,
|
|
618
|
+
[action.data.policyId]: action.data.channelIds,
|
|
619
|
+
};
|
|
620
|
+
case action_types_1.AdminTypes.UNASSIGN_CHANNELS_FROM_ACCESS_CONTROL_POLICY_SUCCESS:
|
|
621
|
+
return {
|
|
622
|
+
...state,
|
|
623
|
+
[action.data.policyId]: action.data.channelIds,
|
|
624
|
+
};
|
|
625
|
+
case action_types_1.UserTypes.LOGOUT_SUCCESS:
|
|
626
|
+
return {};
|
|
627
|
+
default:
|
|
628
|
+
return state;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
575
631
|
exports.default = (0, redux_1.combineReducers)({
|
|
576
632
|
// array of LogObjects each representing a log entry (JSON)
|
|
577
633
|
logs,
|
|
@@ -614,4 +670,8 @@ exports.default = (0, redux_1.combineReducers)({
|
|
|
614
670
|
dataRetentionCustomPoliciesCount,
|
|
615
671
|
// the last trial license the server used.
|
|
616
672
|
prevTrialLicense,
|
|
673
|
+
// object with policy ids as keys and objects representing the policies as values
|
|
674
|
+
accessControlPolicies,
|
|
675
|
+
// object with policy ids as keys and arrays of channel ids as values
|
|
676
|
+
channelsForAccessControlPolicy,
|
|
617
677
|
});
|
|
@@ -110,6 +110,8 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
110
110
|
dataRetentionCustomPolicies: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/data_retention").DataRetentionCustomPolicy>;
|
|
111
111
|
dataRetentionCustomPoliciesCount: any;
|
|
112
112
|
prevTrialLicense: any;
|
|
113
|
+
accessControlPolicies: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/access_control").AccessControlPolicy>;
|
|
114
|
+
channelsForAccessControlPolicy: any;
|
|
113
115
|
}>;
|
|
114
116
|
jobs: import("redux").CombinedState<{
|
|
115
117
|
jobs: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/jobs").Job>;
|
|
@@ -196,6 +196,24 @@ function profiles(state = {}, action) {
|
|
|
196
196
|
const profileAttributes = { ...existingProfile.custom_profile_attributes, ...customAttributeValues };
|
|
197
197
|
return receiveUserProfile(state, { ...existingProfile, custom_profile_attributes: profileAttributes });
|
|
198
198
|
}
|
|
199
|
+
case action_types_1.UserTypes.CLEAR_CPA_VALUES: {
|
|
200
|
+
const { fieldId } = action.data;
|
|
201
|
+
return Object.values(state).reduce((nextState, profile) => {
|
|
202
|
+
// Only modify profiles that have this field value
|
|
203
|
+
if (profile.custom_profile_attributes && profile.custom_profile_attributes[fieldId] !== undefined) {
|
|
204
|
+
const newAttributes = { ...profile.custom_profile_attributes };
|
|
205
|
+
delete newAttributes[fieldId];
|
|
206
|
+
nextState[profile.id] = {
|
|
207
|
+
...profile,
|
|
208
|
+
custom_profile_attributes: newAttributes,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
nextState[profile.id] = profile;
|
|
213
|
+
}
|
|
214
|
+
return nextState;
|
|
215
|
+
}, {});
|
|
216
|
+
}
|
|
199
217
|
case action_types_1.UserTypes.RECEIVED_PROFILES_LIST: {
|
|
200
218
|
const users = action.data;
|
|
201
219
|
return users.reduce(receiveUserProfile, state);
|
package/lib/reducers/index.d.ts
CHANGED
|
@@ -112,6 +112,8 @@ declare const _default: {
|
|
|
112
112
|
dataRetentionCustomPolicies: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/data_retention").DataRetentionCustomPolicy>;
|
|
113
113
|
dataRetentionCustomPoliciesCount: any;
|
|
114
114
|
prevTrialLicense: any;
|
|
115
|
+
accessControlPolicies: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/access_control").AccessControlPolicy>;
|
|
116
|
+
channelsForAccessControlPolicy: any;
|
|
115
117
|
}>;
|
|
116
118
|
jobs: import("redux").CombinedState<{
|
|
117
119
|
jobs: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/jobs").Job>;
|
|
@@ -3,30 +3,10 @@
|
|
|
3
3
|
// See LICENSE.txt for license information.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.createSelector = void 0;
|
|
6
|
-
exports.generateId = generateId;
|
|
7
6
|
exports.defaultMemoize = defaultMemoize;
|
|
8
7
|
exports.createSelectorCreator = createSelectorCreator;
|
|
9
8
|
exports.createStructuredSelector = createStructuredSelector;
|
|
10
|
-
exports.getSortedTrackedSelectors = getSortedTrackedSelectors;
|
|
11
9
|
/* eslint-disable */
|
|
12
|
-
// Generates a RFC-4122 version 4 compliant globally unique identifier.
|
|
13
|
-
function generateId() {
|
|
14
|
-
// implementation taken from http://stackoverflow.com/a/2117523
|
|
15
|
-
let id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
|
|
16
|
-
id = id.replace(/[xy]/g, (c) => {
|
|
17
|
-
const r = Math.floor(Math.random() * 16);
|
|
18
|
-
let v;
|
|
19
|
-
if (c === 'x') {
|
|
20
|
-
v = r;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
// eslint-disable-next-line no-mixed-operators
|
|
24
|
-
v = r & 0x3 | 0x8;
|
|
25
|
-
}
|
|
26
|
-
return v.toString(16);
|
|
27
|
-
});
|
|
28
|
-
return id;
|
|
29
|
-
}
|
|
30
10
|
function defaultEqualityCheck(a, b) {
|
|
31
11
|
return a === b;
|
|
32
12
|
}
|
|
@@ -43,7 +23,7 @@ function areArgumentsShallowlyEqual(equalityCheck, prev, next) {
|
|
|
43
23
|
}
|
|
44
24
|
return true;
|
|
45
25
|
}
|
|
46
|
-
function defaultMemoize(func,
|
|
26
|
+
function defaultMemoize(func, equalityCheck = defaultEqualityCheck) {
|
|
47
27
|
let lastArgs = null;
|
|
48
28
|
let lastResult = null;
|
|
49
29
|
// we reference arguments instead of spreading them for performance reasons
|
|
@@ -52,9 +32,6 @@ function defaultMemoize(func, measure, equalityCheck = defaultEqualityCheck) {
|
|
|
52
32
|
// apply arguments instead of spreading for performance.
|
|
53
33
|
lastResult = func.apply(null, arguments);
|
|
54
34
|
}
|
|
55
|
-
if (measure) {
|
|
56
|
-
measure();
|
|
57
|
-
}
|
|
58
35
|
lastArgs = arguments;
|
|
59
36
|
return lastResult;
|
|
60
37
|
};
|
|
@@ -68,20 +45,14 @@ function getDependencies(funcs) {
|
|
|
68
45
|
}
|
|
69
46
|
return dependencies;
|
|
70
47
|
}
|
|
71
|
-
const trackedSelectors = {};
|
|
72
48
|
function createSelectorCreator(memoize, ...memoizeOptions) {
|
|
73
49
|
return (name, ...funcs) => {
|
|
74
|
-
const id = generateId();
|
|
75
|
-
let recomputations = 0;
|
|
76
|
-
let calls = 0;
|
|
77
50
|
const resultFunc = funcs.pop();
|
|
78
51
|
const dependencies = getDependencies(funcs);
|
|
79
52
|
const memoizedResultFunc = memoize(function () {
|
|
80
|
-
recomputations++;
|
|
81
|
-
trackedSelectors[id].recomputations++;
|
|
82
53
|
// apply arguments instead of spreading for performance.
|
|
83
54
|
return resultFunc?.apply(null, arguments);
|
|
84
|
-
},
|
|
55
|
+
}, ...memoizeOptions);
|
|
85
56
|
// If a selector is called with the exact same arguments we don't need to traverse our dependencies again.
|
|
86
57
|
const selector = memoize(function () {
|
|
87
58
|
const params = [];
|
|
@@ -92,20 +63,9 @@ function createSelectorCreator(memoize, ...memoizeOptions) {
|
|
|
92
63
|
}
|
|
93
64
|
// apply arguments instead of spreading for performance.
|
|
94
65
|
return memoizedResultFunc.apply(null, params);
|
|
95
|
-
}, () => {
|
|
96
|
-
calls++;
|
|
97
|
-
trackedSelectors[id].calls++;
|
|
98
66
|
});
|
|
99
67
|
selector.resultFunc = resultFunc;
|
|
100
68
|
selector.dependencies = dependencies;
|
|
101
|
-
selector.recomputations = () => recomputations;
|
|
102
|
-
selector.resetRecomputations = () => recomputations = 0;
|
|
103
|
-
trackedSelectors[id] = {
|
|
104
|
-
id,
|
|
105
|
-
name,
|
|
106
|
-
calls: 0,
|
|
107
|
-
recomputations: 0,
|
|
108
|
-
};
|
|
109
69
|
return selector;
|
|
110
70
|
};
|
|
111
71
|
}
|
|
@@ -123,43 +83,3 @@ function createStructuredSelector(selectors, selectorCreator = exports.createSel
|
|
|
123
83
|
}, {});
|
|
124
84
|
});
|
|
125
85
|
}
|
|
126
|
-
// resetTrackedSelectors resets all the measurements for memoization effectiveness.
|
|
127
|
-
function resetTrackedSelectors() {
|
|
128
|
-
Object.values(trackedSelectors).forEach((selector) => {
|
|
129
|
-
selector.calls = 0;
|
|
130
|
-
selector.recomputations = 0;
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
// getSortedTrackedSelectors returns an array, sorted by effectivness, containing mesaurement data on all tracked selectors.
|
|
134
|
-
function getSortedTrackedSelectors() {
|
|
135
|
-
let selectors = Object.values(trackedSelectors);
|
|
136
|
-
// Filter out any selector not called
|
|
137
|
-
selectors = selectors.filter(selector => selector.calls > 0);
|
|
138
|
-
const selectorsData = selectors.map((selector) => ({ name: selector.name, effectiveness: effectiveness(selector), recomputations: selector.recomputations, calls: selector.calls }));
|
|
139
|
-
selectorsData.sort((a, b) => {
|
|
140
|
-
// Sort effectiveness ascending
|
|
141
|
-
if (a.effectiveness !== b.effectiveness) {
|
|
142
|
-
return a.effectiveness - b.effectiveness;
|
|
143
|
-
}
|
|
144
|
-
// And everything else descending
|
|
145
|
-
if (a.recomputations !== b.recomputations) {
|
|
146
|
-
return b.recomputations - a.recomputations;
|
|
147
|
-
}
|
|
148
|
-
if (a.calls !== b.calls) {
|
|
149
|
-
return b.calls - a.calls;
|
|
150
|
-
}
|
|
151
|
-
return a.name.localeCompare(b.name);
|
|
152
|
-
});
|
|
153
|
-
return selectorsData;
|
|
154
|
-
}
|
|
155
|
-
function effectiveness(selector) {
|
|
156
|
-
return 100 - ((selector.recomputations / selector.calls) * 100);
|
|
157
|
-
}
|
|
158
|
-
// dumpTrackedSelectorsStatistics prints to console a table containing the measurement data on all tracked selectors.
|
|
159
|
-
function dumpTrackedSelectorsStatistics() {
|
|
160
|
-
const selectors = getSortedTrackedSelectors();
|
|
161
|
-
console.table(selectors); //eslint-disable-line no-console
|
|
162
|
-
}
|
|
163
|
-
window.dumpTrackedSelectorsStatistics = dumpTrackedSelectorsStatistics;
|
|
164
|
-
window.resetTrackedSelectors = resetTrackedSelectors;
|
|
165
|
-
window.getSortedTrackedSelectors = getSortedTrackedSelectors;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Channel, ChannelWithTeamData, ChannelSearchOpts } from '@mattermost/types/channels';
|
|
2
|
+
import type { GlobalState } from '@mattermost/types/store';
|
|
3
|
+
export declare function getAccessControlPolicy(state: GlobalState, id: string): import("@mattermost/types/access_control").AccessControlPolicy;
|
|
4
|
+
export declare const getChannelIdsForAccessControlPolicy: (state: GlobalState, parentId: string) => string[];
|
|
5
|
+
export declare function makeGetChannelsInAccessControlPolicy(): (b: GlobalState, a: {
|
|
6
|
+
policyId: string;
|
|
7
|
+
}) => ChannelWithTeamData[];
|
|
8
|
+
export declare function searchChannelsInheritsPolicy(state: GlobalState, policyId: string, term: string, filters: ChannelSearchOpts): Channel[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getChannelIdsForAccessControlPolicy = void 0;
|
|
6
|
+
exports.getAccessControlPolicy = getAccessControlPolicy;
|
|
7
|
+
exports.makeGetChannelsInAccessControlPolicy = makeGetChannelsInAccessControlPolicy;
|
|
8
|
+
exports.searchChannelsInheritsPolicy = searchChannelsInheritsPolicy;
|
|
9
|
+
const channel_utils_1 = require("mattermost-redux/utils/channel_utils");
|
|
10
|
+
const channels_1 = require("./channels");
|
|
11
|
+
const create_selector_1 = require("../create_selector");
|
|
12
|
+
function getAccessControlPolicy(state, id) {
|
|
13
|
+
return state.entities.admin.accessControlPolicies[id];
|
|
14
|
+
}
|
|
15
|
+
exports.getChannelIdsForAccessControlPolicy = (0, create_selector_1.createSelector)('getChannelIdsForAccessControlPolicy', (state, parentId) => state.entities.admin.channelsForAccessControlPolicy[parentId], (channelIds) => (Array.isArray(channelIds) ? channelIds : []));
|
|
16
|
+
function makeGetChannelsInAccessControlPolicy() {
|
|
17
|
+
return (0, create_selector_1.createSelector)('getChannelsInAccessControlPolicy', (state) => state.entities.channels.channels, (state, props) => (0, exports.getChannelIdsForAccessControlPolicy)(state, props.policyId), (state) => state.entities.teams.teams, (channels, ids, teams) => {
|
|
18
|
+
if (!ids) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const policyChannels = [];
|
|
22
|
+
ids.forEach((channelId) => {
|
|
23
|
+
const channel = channels[channelId];
|
|
24
|
+
if (channel) {
|
|
25
|
+
const team = teams[channel.team_id] || {};
|
|
26
|
+
policyChannels.push({
|
|
27
|
+
...channel,
|
|
28
|
+
team_id: channel.team_id,
|
|
29
|
+
team_display_name: team.display_name || '',
|
|
30
|
+
team_name: team.name || '',
|
|
31
|
+
team_update_at: team.update_at || 0,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return policyChannels;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function searchChannelsInheritsPolicy(state, policyId, term, filters) {
|
|
39
|
+
const channelsInPolicy = makeGetChannelsInAccessControlPolicy();
|
|
40
|
+
const channelArray = channelsInPolicy(state, { policyId });
|
|
41
|
+
let channels = (0, channels_1.filterChannelList)(channelArray, filters);
|
|
42
|
+
channels = (0, channel_utils_1.filterChannelsMatchingTerm)(channels, term);
|
|
43
|
+
return channels;
|
|
44
|
+
}
|
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
3
|
// See LICENSE.txt for license information.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.selectShowChannelBanner = void 0;
|
|
5
|
+
exports.selectShowChannelBanner = exports.selectChannelBannerEnabled = void 0;
|
|
6
6
|
const channels_1 = require("@mattermost/types/channels");
|
|
7
7
|
const constants_1 = require("mattermost-redux/constants");
|
|
8
8
|
const channels_2 = require("mattermost-redux/selectors/entities/channels");
|
|
9
9
|
const general_1 = require("mattermost-redux/selectors/entities/general");
|
|
10
|
-
const
|
|
10
|
+
const selectChannelBannerEnabled = (state) => {
|
|
11
11
|
const license = (0, general_1.getLicense)(state);
|
|
12
|
-
|
|
12
|
+
return license?.SkuShortName === constants_1.General.SKUEnterpriseAdvanced;
|
|
13
|
+
};
|
|
14
|
+
exports.selectChannelBannerEnabled = selectChannelBannerEnabled;
|
|
15
|
+
const selectShowChannelBanner = (state, channelId) => {
|
|
16
|
+
const enabled = (0, exports.selectChannelBannerEnabled)(state);
|
|
17
|
+
if (!enabled) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
13
20
|
const channelBannerInfo = (0, channels_2.getChannelBanner)(state, channelId);
|
|
14
21
|
const channel = (0, channels_2.getChannel)(state, channelId);
|
|
15
22
|
const isValidChannelType = Boolean(channel && (channel.type === constants_1.General.OPEN_CHANNEL || channel.type === constants_1.General.PRIVATE_CHANNEL));
|
|
16
|
-
return
|
|
23
|
+
return isValidChannelType && (0, channels_1.channelBannerEnabled)(channelBannerInfo);
|
|
17
24
|
};
|
|
18
25
|
exports.selectShowChannelBanner = selectShowChannelBanner;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { GlobalState } from '@mattermost/types/store';
|
|
2
|
+
export declare function getReportAProblemLink(state: GlobalState): string;
|
|
3
|
+
export declare const getSystemInfoMailtoLink: import("mattermost-redux/selectors/create_selector").OutputParametricSelector<GlobalState, string | undefined, string, (res1: string, res2: string, res3: string | undefined, res4: string | undefined, res5: string | undefined, res6: string | undefined) => string>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getSystemInfoMailtoLink = void 0;
|
|
6
|
+
exports.getReportAProblemLink = getReportAProblemLink;
|
|
7
|
+
const create_selector_1 = require("mattermost-redux/selectors/create_selector");
|
|
8
|
+
const browser_info_1 = require("mattermost-redux/utils/browser_info");
|
|
9
|
+
const general_1 = require("./general");
|
|
10
|
+
const teams_1 = require("./teams");
|
|
11
|
+
const users_1 = require("./users");
|
|
12
|
+
function getReportAProblemLink(state) {
|
|
13
|
+
const config = (0, general_1.getConfig)(state);
|
|
14
|
+
const type = config.ReportAProblemType;
|
|
15
|
+
switch (type) {
|
|
16
|
+
case 'email':
|
|
17
|
+
return (0, exports.getSystemInfoMailtoLink)(state, config.ReportAProblemMail);
|
|
18
|
+
case 'link':
|
|
19
|
+
if (config.ReportAProblemLink) {
|
|
20
|
+
return config.ReportAProblemLink;
|
|
21
|
+
}
|
|
22
|
+
// falls through
|
|
23
|
+
case 'default': {
|
|
24
|
+
const isLicensed = (0, general_1.getLicense)(state).IsLicensed === 'true';
|
|
25
|
+
if (isLicensed) {
|
|
26
|
+
return 'https://mattermost.com/pl/report_a_problem_licensed';
|
|
27
|
+
}
|
|
28
|
+
return 'https://mattermost.com/pl/report_a_problem_unlicensed';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
exports.getSystemInfoMailtoLink = (0, create_selector_1.createSelector)('getSystemInfoMailtoLink', users_1.getCurrentUserId, teams_1.getCurrentTeamId, (state) => (0, general_1.getConfig)(state).Version, (state) => (0, general_1.getConfig)(state).BuildNumber, (state) => (0, general_1.getConfig)(state).SiteName, (state, supportEmail) => supportEmail, (currentUserId, currentTeamId, version, buildNumber, siteName, supportEmail) => {
|
|
34
|
+
const { browser, browserVersion } = (0, browser_info_1.getBrowserInfo)();
|
|
35
|
+
const platformName = (0, browser_info_1.getPlatformInfo)();
|
|
36
|
+
const subject = `Problem with ${siteName || 'Mattermost'} app`;
|
|
37
|
+
const body = `
|
|
38
|
+
System Information:
|
|
39
|
+
- User ID: ${currentUserId}
|
|
40
|
+
- Team ID: ${currentTeamId}
|
|
41
|
+
- Server Version: ${version} (${buildNumber})
|
|
42
|
+
- Browser: ${browser} ${browserVersion}
|
|
43
|
+
- Platform: ${platformName}
|
|
44
|
+
`.trim();
|
|
45
|
+
return `mailto:${supportEmail || ''}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
46
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getBrowserInfo = getBrowserInfo;
|
|
6
|
+
exports.getPlatformInfo = getPlatformInfo;
|
|
7
|
+
function getBrowserInfo() {
|
|
8
|
+
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
9
|
+
let browser = 'Unknown';
|
|
10
|
+
let browserVersion = 'Unknown';
|
|
11
|
+
// Check if it's Mattermost Desktop App first
|
|
12
|
+
if (userAgent.includes('mattermost')) {
|
|
13
|
+
browser = 'Mattermost Desktop App';
|
|
14
|
+
const match = userAgent.match(/mattermost\/(\d+(\.\d+)*)/i);
|
|
15
|
+
if (match && match[1]) {
|
|
16
|
+
browserVersion = match[1];
|
|
17
|
+
}
|
|
18
|
+
return { browser, browserVersion };
|
|
19
|
+
}
|
|
20
|
+
// Simple browser detection - order matters!
|
|
21
|
+
if (userAgent.includes('edge/')) {
|
|
22
|
+
browser = 'Edge';
|
|
23
|
+
}
|
|
24
|
+
else if (userAgent.includes('edg/')) {
|
|
25
|
+
browser = 'Edge Chromium';
|
|
26
|
+
}
|
|
27
|
+
else if (userAgent.includes('chrome/')) {
|
|
28
|
+
if (userAgent.includes('opr/')) {
|
|
29
|
+
browser = 'Opera';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
browser = 'Chrome';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (userAgent.includes('safari/') && userAgent.includes('version/')) {
|
|
36
|
+
browser = 'Safari';
|
|
37
|
+
}
|
|
38
|
+
else if (userAgent.includes('firefox/')) {
|
|
39
|
+
browser = 'Firefox';
|
|
40
|
+
}
|
|
41
|
+
// Get browser version
|
|
42
|
+
let match;
|
|
43
|
+
if (browser === 'Edge') {
|
|
44
|
+
match = userAgent.match(/edge\/(\d+)/i);
|
|
45
|
+
}
|
|
46
|
+
else if (browser === 'Edge Chromium') {
|
|
47
|
+
match = userAgent.match(/edg\/(\d+)/i);
|
|
48
|
+
}
|
|
49
|
+
else if (browser === 'Opera') {
|
|
50
|
+
match = userAgent.match(/opr\/(\d+)/i);
|
|
51
|
+
}
|
|
52
|
+
else if (browser === 'Safari') {
|
|
53
|
+
match = userAgent.match(/version\/(\d+)/i);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
match = userAgent.match(/(firefox|chrome)\/(\d+)/i);
|
|
57
|
+
if (match) {
|
|
58
|
+
match[1] = match[2]; // Align with other matches where version is in group 1
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (match && match[1]) {
|
|
62
|
+
browserVersion = match[1];
|
|
63
|
+
}
|
|
64
|
+
return { browser, browserVersion };
|
|
65
|
+
}
|
|
66
|
+
function getPlatformInfo() {
|
|
67
|
+
// Casting to undefined in case it is deprecated in any browser
|
|
68
|
+
const platform = window.navigator.platform;
|
|
69
|
+
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
70
|
+
let platformName = 'Unknown';
|
|
71
|
+
// First try using platform
|
|
72
|
+
if (platform) {
|
|
73
|
+
if (platform.toLowerCase().includes('win')) {
|
|
74
|
+
platformName = 'Windows';
|
|
75
|
+
}
|
|
76
|
+
else if (platform.toLowerCase().includes('mac')) {
|
|
77
|
+
platformName = 'MacOS';
|
|
78
|
+
}
|
|
79
|
+
else if (platform.toLowerCase().includes('linux')) {
|
|
80
|
+
platformName = 'Linux';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Fallback to userAgent if platform didn't work
|
|
84
|
+
if (platformName === 'Unknown') {
|
|
85
|
+
if (userAgent.includes('windows')) {
|
|
86
|
+
platformName = 'Windows';
|
|
87
|
+
}
|
|
88
|
+
else if (userAgent.includes('mac os x')) {
|
|
89
|
+
platformName = 'MacOS';
|
|
90
|
+
}
|
|
91
|
+
else if (userAgent.includes('linux')) {
|
|
92
|
+
platformName = 'Linux';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return platformName;
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mattermost-redux",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.9.0",
|
|
4
4
|
"description": "Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mattermost"
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"directory": "webapp/platform/mattermost-redux"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@mattermost/client": "10.
|
|
43
|
-
"@mattermost/types": "10.
|
|
42
|
+
"@mattermost/client": "10.9.0",
|
|
43
|
+
"@mattermost/types": "10.9.0",
|
|
44
44
|
"@redux-devtools/extension": "^3.2.3",
|
|
45
45
|
"lodash": "^4.17.21",
|
|
46
46
|
"moment-timezone": "^0.5.38",
|