Apply data retention policy (#1122)

This commit is contained in:
enahum 2017-11-12 08:33:42 -03:00 committed by GitHub
parent 380f5d884a
commit b7fe369fab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 30 deletions

View file

@ -1,10 +1,10 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {PostTypes} from 'mattermost-redux/action_types';
import {GeneralTypes, PostTypes} from 'mattermost-redux/action_types';
import {Client4} from 'mattermost-redux/client';
import {General} from 'mattermost-redux/constants';
import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general';
import {getClientConfig, getDataRetentionPolicy, getLicenseConfig} from 'mattermost-redux/actions/general';
import {getPosts} from 'mattermost-redux/actions/posts';
import {getMyTeams, getMyTeamMembers, selectTeam} from 'mattermost-redux/actions/teams';
@ -16,11 +16,21 @@ import {
export function loadConfigAndLicense() {
return async (dispatch, getState) => {
const [config, license] = await Promise.all([
const [configData, licenseData] = await Promise.all([
getClientConfig()(dispatch, getState),
getLicenseConfig()(dispatch, getState)
]);
const config = configData.data || {};
const license = licenseData.data || {};
if (config.DataRetentionEnableMessageDeletion && config.DataRetentionEnableMessageDeletion === 'true' &&
license.IsLicensed === 'true' && license.DataRetention === 'true') {
getDataRetentionPolicy()(dispatch, getState);
} else {
dispatch({type: GeneralTypes.RECEIVED_DATA_RETENTION_POLICY, data: {}});
}
return {config, license};
};
}

View file

@ -9,6 +9,7 @@ const state = {
appState: false,
credentials: {},
config: {},
dataRetentionPolicy: {},
deviceToken: '',
license: {},
serverVersion: ''
@ -45,6 +46,9 @@ const state = {
preferences: {
myPreferences: {}
},
search: {
recent: []
},
typing: {}
},
errors: [],
@ -108,6 +112,10 @@ const state = {
status: 'not_started',
error: null
},
dataRetentionPolicy: {
status: 'not_started',
error: null
},
license: {
status: 'not_started',
error: null
@ -252,8 +260,7 @@ const state = {
navigation: '',
views: {
channel: {
drafts: {},
loading: false
drafts: {}
},
fetchCache: {},
i18n: {
@ -270,7 +277,9 @@ const state = {
selectServer: {
serverUrl: Config.DefaultServerUrl
},
team: {},
team: {
lastTeamId: ''
},
thread: {
drafts: {}
}

View file

@ -4,7 +4,7 @@
import DeviceInfo from 'react-native-device-info';
import {ViewTypes} from 'app/constants';
import Config from 'assets/config';
import initialState from 'app/initial_state';
export function messageRetention() {
return (next) => (action) => {
@ -23,6 +23,7 @@ export function messageRetention() {
// Keep only the last 60 messages for the last 5 viewed channels in each team
// and apply data retention on those posts if applies
return next(cleanupState(action));
} else if (action.type === ViewTypes.DATA_CLEANUP) {
const nextAction = cleanupState(action, true);
@ -36,8 +37,22 @@ export function messageRetention() {
function resetStateForNewVersion(action) {
const {payload} = action;
const lastChannelForTeam = getLastChannelForTeam(payload);
let users = {};
let general = initialState.entities.general;
if (payload.entities.general) {
general = payload.entities.general;
}
let teams = initialState.entities.teams;
if (payload.entities.teams) {
teams = {
currentTeamId: payload.entities.teams.currentTeamId,
teams: payload.entities.teams.teams,
myMembers: payload.entities.teams.myMembers
};
}
let users = initialState.entities.users;
if (payload.entities.users) {
const currentUserId = payload.entities.users.currentUserId;
if (currentUserId) {
@ -50,38 +65,74 @@ function resetStateForNewVersion(action) {
}
}
let preferences = initialState.entities.preferences;
if (payload.entities.preferences) {
preferences = payload.entities.preferences;
}
let search = initialState.entities.search;
if (payload.entities.search && payload.entities.search.recent) {
search = {
recent: payload.entities.search.recent
};
}
let channelDrafts = initialState.views.channel.drafts;
if (payload.views.channel && payload.views.channel.drafts) {
channelDrafts = payload.views.channel.drafts;
}
let i18n = initialState.views.i18n;
if (payload.views.i18n) {
i18n = payload.views.i18n;
}
let fetchCache = initialState.views.fetchCache;
if (payload.views.fetchCache) {
fetchCache = payload.views.fetchCache;
}
let lastTeamId = initialState.views.team.lastTeamId;
if (payload.views.team && payload.views.team.lastTeamId) {
lastTeamId = payload.views.team.lastTeamId;
}
let threadDrafts = initialState.views.thread.drafts;
if (payload.views.thread && payload.views.thread.drafts) {
threadDrafts = payload.views.thread.drafts;
}
let selectServer = initialState.views.selectServer;
if (payload.views.selectServer) {
selectServer = payload.views.selectServer;
}
const nextState = {
app: {
build: DeviceInfo.getBuildNumber(),
version: DeviceInfo.getVersion()
},
entities: {
general: payload.entities.general,
teams: {
currentTeamId: payload.entities.teams.currentTeamId,
teams: payload.entities.teams.teams,
myMembers: payload.entities.teams.myMembers
},
general,
teams,
users,
preferences: payload.entities.preferences,
search: {
recent: payload.entities.search ? payload.entities.search.recent : {}
}
preferences,
search
},
views: {
channel: {
drafts: payload.views.channel.drafts
drafts: channelDrafts
},
i18n: payload.views.i18n,
fetchCache: payload.views.fetchCache,
i18n,
fetchCache,
team: {
lastTeamId: payload.views.team.lastTeamId,
lastTeamId,
lastChannelForTeam
},
thread: {
drafts: payload.views.thread.drafts
drafts: threadDrafts
},
selectServer: payload.views.selectServer
selectServer
}
};
@ -126,7 +177,12 @@ function cleanupState(action, keepCurrent = false) {
}
};
const retentionPeriod = Config.EnableMessageRetention ? Config.MessageRetentionPeriod + 1 : 0;
let retentionPeriod = 0;
if (resetPayload.entities.general && resetPayload.entities.general.dataRetentionPolicy &&
resetPayload.entities.general.dataRetentionPolicy.message_deletion_enabled) {
retentionPeriod = resetPayload.entities.general.dataRetentionPolicy.message_retention_cutoff;
}
const postIdsToKeep = Object.values(lastChannelForTeam).reduce((array, channelIds) => {
const ids = channelIds.reduce((result, id) => {
// we need to check that the channel id is not already included
@ -152,9 +208,7 @@ function cleanupState(action, keepCurrent = false) {
const post = payload.entities.posts.posts[postId];
if (post) {
const skip = keepCurrent && currentChannelId === post.channel_id;
if (!skip && retentionPeriod && (Date.now() - post.create_at) / (1000 * 3600 * 24) > retentionPeriod) {
if (retentionPeriod && post.create_at < retentionPeriod) {
const postsInChannel = nextEntitites.posts.postsInChannel[post.channel_id] || [];
const index = postsInChannel.indexOf(postId);
if (index !== -1) {

View file

@ -1,7 +1,5 @@
{
"DefaultServerUrl": "",
"EnableMessageRetention": false,
"MessageRetentionPeriod": 30,
"TestServerUrl": "http://localhost:8065",
"DefaultTheme": "default",
"ShowErrorsList": false,