Merge branch 'master' of github.com:ONLYOFFICE/CommunityServer-AspNetCore

This commit is contained in:
Alexey Safronov 2019-09-03 09:30:07 +03:00
commit b842f2d86f
16 changed files with 148 additions and 53 deletions

View File

@ -40,8 +40,7 @@ namespace ASC.Core.Users
public UserInfo()
{
Status = EmployeeStatus.Active;
ActivationStatus = EmployeeActivationStatus.NotActivated;
Contacts = new List<string>();
ActivationStatus = EmployeeActivationStatus.NotActivated;
LastModified = DateTime.UtcNow;
}
@ -166,7 +165,7 @@ namespace ASC.Core.Users
internal string ContactsToString()
{
if (Contacts.Count == 0) return null;
if (Contacts == null || Contacts.Count == 0) return null;
var sBuilder = new StringBuilder();
foreach (var contact in Contacts)
{
@ -177,12 +176,19 @@ namespace ASC.Core.Users
internal UserInfo ContactsFromString(string contacts)
{
if (string.IsNullOrEmpty(contacts)) return this;
Contacts.Clear();
foreach (var contact in contacts.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries))
{
Contacts.Add(contact);
}
if (string.IsNullOrEmpty(contacts)) return this;
if (Contacts == null)
{
Contacts = new List<string>();
}
else
{
Contacts.Clear();
}
Contacts.AddRange(contacts.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries));
return this;
}
}

View File

@ -81,6 +81,8 @@ namespace ASC.Core.Users
public static void ConvertExternalContactsToOrdinary(this UserInfo ui)
{
var ldapUserContacts = ui.Contacts;
if (ui.Contacts == null) return;
var newContacts = new List<string>();

View File

@ -2,7 +2,7 @@ import React, { Suspense } from "react";
import { connect } from "react-redux";
import { BrowserRouter, Switch } from "react-router-dom";
import { Loader } from "asc-web-components";
import PeopleLayout from "./components/Layout";
import PeopleLayout from "./components/Layout/index";
import Home from "./components/pages/Home";
import PrivateRoute from "./helpers/privateRoute";
import Profile from './components/pages/Profile';

View File

@ -0,0 +1,58 @@
import i18n from "i18next";
import Backend from "i18next-xhr-backend";
import config from "../../../package.json";
const newInstance = i18n.createInstance();
if (process.env.NODE_ENV === "production") {
newInstance
.use(Backend)
.init({
lng: 'en',
fallbackLng: "en",
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === 'lowercase') return value.toLowerCase();
return value;
}
},
react: {
useSuspense: false
},
backend: {
loadPath: `${config.homepage}/locales/Layout/{{lng}}/{{ns}}.json`
}
});
} else if (process.env.NODE_ENV === "development") {
const resources = {
en: {
translation: require("./locales/en/translation.json")
}
};
newInstance.init({
resources: resources,
lng: 'en',
fallbackLng: "en",
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === 'lowercase') return value.toLowerCase();
return value;
}
},
react: {
useSuspense: false
}
});
}
export default newInstance;

View File

@ -3,12 +3,13 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withRouter } from "react-router";
import { Layout, Toast } from 'asc-web-components';
import { logout } from '../store/auth/actions';
import { withTranslation } from 'react-i18next';
import { logout } from '../../store/auth/actions';
import { withTranslation, I18nextProvider } from 'react-i18next';
import i18n from "./i18n";
class PeopleLayout extends React.Component {
class PurePeopleLayout extends React.Component {
shouldComponentUpdate(nextProps) {
if(this.props.hasChanges !== nextProps.hasChanges) {
if (this.props.hasChanges !== nextProps.hasChanges) {
return true;
}
@ -36,13 +37,13 @@ class PeopleLayout extends React.Component {
const currentUserActions = [
{
key: 'ProfileBtn', label: t('Resource:Profile'), onClick: this.onProfileClick
key: 'ProfileBtn', label: t('Profile'), onClick: this.onProfileClick
},
{
key: 'AboutBtn', label: t('Resource:AboutCompanyTitle'), onClick: this.onAboutClick
key: 'AboutBtn', label: t('AboutCompanyTitle'), onClick: this.onAboutClick
},
{
key: 'LogoutBtn', label: t('Resource:LogoutButton'), onClick: this.onLogoutClick
key: 'LogoutBtn', label: t('LogoutButton'), onClick: this.onLogoutClick
},
];
@ -64,9 +65,6 @@ class PeopleLayout extends React.Component {
}
};
PeopleLayout.propTypes = {
logout: PropTypes.func.isRequired
};
const getAvailableModules = (modules) => {
const separator = { seporator: true, id: 'nav-seporator-1' };
@ -95,4 +93,12 @@ function mapStateToProps(state) {
};
}
export default connect(mapStateToProps, { logout })(withRouter(withTranslation()(PeopleLayout)));
const PeopleLayoutContainer = withTranslation()(PurePeopleLayout);
const PeopleLayout = (props) => <I18nextProvider i18n={i18n}><PeopleLayoutContainer {...props} /></I18nextProvider>;
PeopleLayout.propTypes = {
logout: PropTypes.func.isRequired
};
export default connect(mapStateToProps, { logout })(withRouter((PeopleLayout)));

View File

@ -0,0 +1,5 @@
{
"Profile": "Profile",
"AboutCompanyTitle": "About this program",
"LogoutButton": "Sign Out"
}

View File

@ -59,7 +59,7 @@ const getGroup = filterValues => {
return groupId || null;
};
const SectionFilterContent = React.memo(({
const SectionFilterContent = ({
fetchPeople,
filter,
onLoading,
@ -195,12 +195,12 @@ const SectionFilterContent = React.memo(({
return (
<FilterInput
getFilterData={getData}
getSortData={()=> getSortData(t)}
getSortData={getSortData.bind(this, t)}
selectedFilterData={selectedFilterData}
onFilter={onFilter}
/>
);
});
};
function mapStateToProps(state) {
return {

View File

@ -29,7 +29,7 @@ const wrapperStyle = {
alignItems: "center"
};
const SectionHeaderContent = React.memo(({
const SectionHeaderContent = ({
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
@ -151,14 +151,14 @@ const SectionHeaderContent = React.memo(({
iconName='VerticalDotsIcon'
size={16}
color='#A3A9AE'
getData={() => contextOptions(t)}
getData={contextOptions.bind(this, t)}
isDisabled={false}/>
}
</div>
: <Text.ContentHeader>{t("People")}</Text.ContentHeader>
)
);
});
};
const mapStateToProps = (state) => {
return {

View File

@ -20,7 +20,7 @@ import {
} from "./Section";
import { setSelected } from "../../../store/people/actions";
class Home extends React.Component {
class PureHome extends React.Component {
constructor(props) {
super(props);
@ -101,7 +101,7 @@ class Home extends React.Component {
} = this.state;
const t = this.props.t;
return (
<I18nextProvider i18n={i18n}>
<>
<RequestLoader
visible={this.state.isLoading}
zIndex={256}
@ -138,17 +138,11 @@ class Home extends React.Component {
<SectionPagingContent onLoading={this.onLoading} />
}
/>
</I18nextProvider>
</>
);
}
}
Home.propTypes = {
users: PropTypes.array.isRequired,
history: PropTypes.object.isRequired,
isLoaded: PropTypes.bool
};
function mapStateToProps(state) {
return {
users: state.people.users,
@ -158,7 +152,17 @@ function mapStateToProps(state) {
};
}
const HomeContainer = withTranslation()(PureHome);
const Home = (props) => <I18nextProvider i18n={i18n}><HomeContainer {...props}/></I18nextProvider>;
Home.propTypes = {
users: PropTypes.array.isRequired,
history: PropTypes.object.isRequired,
isLoaded: PropTypes.bool
};
export default connect(
mapStateToProps,
{ setSelected }
)(withRouter(withTranslation()(Home)));
)(withRouter(Home));

View File

@ -1,5 +1,7 @@
{
"Article": {},
"Article": {
},
"pages": {
"Profile": {
"Resource": [

View File

@ -556,7 +556,6 @@ namespace ASC.Employee.Core.Controllers
if (CoreContext.UserManager.IsSystemUser(user.ID))
throw new SecurityException();
user.Contacts.Clear();
UpdateContacts(memberModel.Contacts, user);
CoreContext.UserManager.SaveUserInfo(Tenant, user);
return new EmployeeWraperFull(user, ApiContext);
@ -1165,9 +1164,18 @@ namespace ASC.Employee.Core.Controllers
private void UpdateContacts(IEnumerable<Contact> contacts, UserInfo user)
{
SecurityContext.DemandPermissions(Tenant, new UserSecurityProvider(user.ID), Constants.Action_EditUser);
user.Contacts.Clear();
if (contacts == null) return;
if (user.Contacts == null)
{
user.Contacts = new List<string>();
}
else
{
user.Contacts.Clear();
}
foreach (var contact in contacts)
{
user.Contacts.Add(contact.Type);
@ -1180,6 +1188,11 @@ namespace ASC.Employee.Core.Controllers
SecurityContext.DemandPermissions(Tenant, new UserSecurityProvider(user.ID), Constants.Action_EditUser);
if (contacts == null) return;
if (user.Contacts == null)
{
user.Contacts = new List<string>();
}
foreach (var contact in contacts)
{
var index = user.Contacts.IndexOf(contact.Type);

View File

@ -217,7 +217,10 @@ namespace ASC.Web.Api.Models
private void FillConacts(UserInfo userInfo)
{
if (userInfo.Contacts == null) return;
var contacts = new List<Contact>();
for (var i = 0; i < userInfo.Contacts.Count; i += 2)
{
if (i + 1 < userInfo.Contacts.Count)

View File

@ -384,7 +384,6 @@ namespace ASC.Api.Settings
throw new BillingException(Resource.ErrorNotAllowedOption, "WhiteLabel");
}
var tenantId = TenantProvider.CurrentTenantID;
var _tenantWhiteLabelSettings = TenantWhiteLabelSettings.Load();
if (model.Logo != null)
@ -396,7 +395,7 @@ namespace ASC.Api.Settings
}
_tenantWhiteLabelSettings.LogoText = model.LogoText;
_tenantWhiteLabelSettings.Save(tenantId);
_tenantWhiteLabelSettings.Save(Tenant.TenantId);
}
@ -407,7 +406,6 @@ namespace ASC.Api.Settings
{
if (model.Attachments != null && model.Attachments.Any())
{
var tenantId = TenantProvider.CurrentTenantID;
var _tenantWhiteLabelSettings = TenantWhiteLabelSettings.Load();
foreach (var f in model.Attachments)
@ -419,7 +417,7 @@ namespace ASC.Api.Settings
using var inputStream = f.OpenReadStream();
_tenantWhiteLabelSettings.SetLogoFromStream(logoType, fileExt, inputStream);
}
_tenantWhiteLabelSettings.Save(tenantId);
_tenantWhiteLabelSettings.Save(Tenant.TenantId);
}
else
{
@ -975,8 +973,8 @@ namespace ASC.Api.Settings
});
}
var hits = StatisticManager.GetHitsByPeriod(TenantProvider.CurrentTenantID, from, to);
var hosts = StatisticManager.GetHostsByPeriod(TenantProvider.CurrentTenantID, from, to);
var hits = StatisticManager.GetHitsByPeriod(Tenant.TenantId, from, to);
var hosts = StatisticManager.GetHostsByPeriod(Tenant.TenantId, from, to);
if (hits.Count == 0 || hosts.Count == 0) return points;

View File

@ -146,7 +146,7 @@ namespace ASC.Api.Settings
return ToSmtpOperationStatus();
}
private static SmtpOperationStatus ToSmtpOperationStatus()
private SmtpOperationStatus ToSmtpOperationStatus()
{
var operations = SMTPTasks.GetTasks().ToList();
@ -162,7 +162,7 @@ namespace ASC.Api.Settings
var operation =
operations
.FirstOrDefault(t => t.GetProperty<int>(SmtpOperation.OWNER) == TenantProvider.CurrentTenantID);
.FirstOrDefault(t => t.GetProperty<int>(SmtpOperation.OWNER) == Tenant.TenantId);
if (operation == null)
{

View File

@ -31,7 +31,6 @@ using System.Web;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Web.Studio.Utility;
using Microsoft.AspNetCore.Http;
using SecurityContext = ASC.Core.SecurityContext;
@ -175,9 +174,9 @@ namespace ASC.Web.Core
httpContext.SetCookies(CookiesType.AuthKey, cookie);
}
public static int GetLifeTime()
public static int GetLifeTime(int tenantId)
{
return TenantCookieSettings.GetForTenant(TenantProvider.CurrentTenantID).LifeTime;
return TenantCookieSettings.GetForTenant(tenantId).LifeTime;
}
public static void ResetUserCookie(this HttpContext httpContext, int tenantId, Guid? userId = null)

View File

@ -115,11 +115,10 @@ namespace ASC.Web.Core.Users
CacheNotify.Subscribe((data) =>
{
var userId = new Guid(data.UserID.ToByteArray());
var size = FromCahe(data.Size);
try
{
Photofiles.TryGetValue(CacheSize.Big, out var dict);
Photofiles.TryGetValue(data.Size, out var dict);
dict?.TryRemove(userId, out _);
//var storage = GetDataStore();
//storage.DeleteFiles("", data.UserID + "*.*", false);