package com.constellio.app.ui.pages.base;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import com.constellio.app.modules.rm.ConstellioRMModule;
import com.constellio.app.modules.rm.extensions.api.RMModuleExtensions;
import com.constellio.app.modules.rm.extensions.api.reports.RMReportBuilderFactories;
import com.constellio.model.services.contents.ContentVersionDataSummary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.constellio.app.entities.navigation.NavigationConfig;
import com.constellio.app.entities.navigation.NavigationItem;
import com.constellio.app.extensions.AppLayerCollectionExtensions;
import com.constellio.app.extensions.AppLayerSystemExtensions;
import com.constellio.app.modules.rm.ui.builders.UserToVOBuilder;
import com.constellio.app.services.collections.CollectionsManager;
import com.constellio.app.services.extensions.ConstellioModulesManagerImpl;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.app.services.factories.ConstellioFactories;
import com.constellio.app.services.schemasDisplay.SchemasDisplayManager;
import com.constellio.app.ui.entities.RecordVO;
import com.constellio.app.ui.entities.RecordVO.VIEW_MODE;
import com.constellio.app.ui.entities.UserVO;
import com.constellio.app.ui.framework.components.ComponentState;
import com.constellio.app.ui.pages.base.BaseView.ViewEnterListener;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.MetadataSchema;
import com.constellio.model.entities.schemas.MetadataSchemaType;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.records.RecordUtils;
import com.constellio.model.services.records.SchemasRecordsServices;
import com.constellio.model.services.search.SearchServices;
import com.constellio.model.services.security.roles.Roles;
import com.constellio.model.services.users.UserServices;
import com.constellio.model.services.users.UserServicesRuntimeException.UserServicesRuntimeException_UserIsNotInCollection;
import static com.constellio.app.ui.i18n.i18n.$;
@SuppressWarnings("serial")
public abstract class BasePresenter<T extends BaseView> implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(BasePresenter.class);
protected final T view;
protected final String collection;
protected transient ModelLayerFactory modelLayerFactory;
protected transient AppLayerFactory appLayerFactory;
private BasePresenterUtils presenterUtils;
protected transient AppLayerCollectionExtensions appCollectionExtentions;
protected transient AppLayerSystemExtensions appSystemExtentions;
private NavigationConfig config;
public BasePresenter(T view) {
this(view, view.getConstellioFactories(), view.getSessionContext());
}
public BasePresenter(final T view, ConstellioFactories constellioFactories, SessionContext sessionContext) {
this.view = view;
view.addViewEnterListener(new ViewEnterListener() {
@Override
public void viewEntered(String params) {
}
@Override
public void afterInit(String params) {
if (!isViewVisibleToCurrentUser(params)) {
LOGGER.warn("Error does not have access to the page");
view.navigate().to().home();
}
}
});
this.collection = sessionContext.getCurrentCollection();
this.presenterUtils = new BasePresenterUtils(constellioFactories, sessionContext);
init();
}
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
init();
}
private void init() {
modelLayerFactory = presenterUtils.modelLayerFactory();
appLayerFactory = presenterUtils.appLayerFactory();
appCollectionExtentions = appLayerFactory.getExtensions().forCollection(collection);
appSystemExtentions = appLayerFactory.getExtensions().getSystemWideExtensions();
}
private boolean isViewVisibleToCurrentUser(String params) {
User user = getCurrentUser();
List<String> restrictedRecordIds = getRestrictedRecordIds(params);
List<Record> restrictedRecords = new ArrayList<>();
if (restrictedRecordIds != null) {
for (String recordId : restrictedRecordIds) {
restrictedRecords.add(recordServices().getDocumentById(recordId));
}
}
String restrictedRecordsCollection = new RecordUtils().getRecordsCollection(restrictedRecords);
if (restrictedRecordsCollection != null && !restrictedRecordsCollection.equals(user.getCollection())) {
UserServices userServices = modelLayerFactory.newUserServices();
try {
User userInOtherCollection = userServices.getUserInCollection(user.getUsername(), restrictedRecordsCollection);
boolean access = hasPageAccess(params, userInOtherCollection, restrictedRecords);
if (access) {
//Switching to other collection
UserToVOBuilder voBuilder = new UserToVOBuilder();
SessionContext sessionContext = presenterUtils.sessionContext;
UserVO newUserVO = voBuilder
.build(userInOtherCollection.getWrappedRecord(), VIEW_MODE.DISPLAY, sessionContext);
sessionContext.setCurrentCollection(restrictedRecordsCollection);
sessionContext.setCurrentUser(newUserVO);
view.updateUI();
return true;
} else {
return false;
}
} catch (UserServicesRuntimeException_UserIsNotInCollection e) {
return false;
}
} else {
return hasPageAccess(params, user, restrictedRecords);
}
}
private boolean hasPageAccess(final String params, final User user, List<Record> restrictedRecords) {
boolean result;
if (user != null) {
AppLayerCollectionExtensions extensions = appLayerFactory.getExtensions().forCollectionOf(user);
boolean pageAccessDefaultValue = hasPageAccess(params, user);
boolean pageAccess = extensions.hasPageAccess(pageAccessDefaultValue, getClass(), params, user);
boolean restrictedRecordsAccess = true;
if (!restrictedRecords.isEmpty()) {
for (final Record restrictedRecord : restrictedRecords) {
boolean restrictedRecordAccessDefaultValue = hasRestrictedRecordAccess(params, user, restrictedRecord);
boolean restrictedRecordAccess = extensions.hasRestrictedRecordAccess(restrictedRecordAccessDefaultValue,
getClass(), params, user, restrictedRecord);
if (!restrictedRecordAccess) {
restrictedRecordsAccess = false;
}
}
}
result = restrictedRecordsAccess && pageAccess;
} else {
result = false;
}
return result;
}
public ComponentState getStateFor(NavigationItem item) {
return item.getStateFor(getCurrentUser(), appLayerFactory);
}
protected abstract boolean hasPageAccess(String params, User user);
protected boolean hasRestrictedRecordAccess(String params, User user, Record restrictedRecord) {
return true;
}
protected List<String> getRestrictedRecordIds(String params) {
return null;
}
protected SchemasRecordsServices coreSchemas() {
return new SchemasRecordsServices(collection, modelLayerFactory);
}
protected MetadataSchemaTypes types() {
return presenterUtils.types();
}
protected MetadataSchemaType schemaType(String code) {
return presenterUtils.schemaType(code);
}
protected MetadataSchema schema(String code) {
return presenterUtils.schema(code);
}
protected User getCurrentUser() {
return presenterUtils.getCurrentUser();
}
public final void clearCurrentUserCache() {
presenterUtils.clearCurrentUserCache();
}
protected Locale getCurrentLocale() {
return presenterUtils.getCurrentLocale();
}
protected UserServices userServices() {
return modelLayerFactory.newUserServices();
}
protected final RecordServices recordServices() {
return presenterUtils.recordServices();
}
protected final PresenterService presenterService() {
return presenterUtils.presenterService();
}
protected final SearchServices searchServices() {
return presenterUtils.searchServices();
}
protected final SchemasDisplayManager schemasDisplayManager() {
return presenterUtils.schemasDisplayManager();
}
protected final CollectionsManager collectionsManager() {
return presenterUtils.getCollectionManager();
}
public String buildString(List<String> list) {
return presenterUtils.buildString(list);
}
public final List<String> getAllRecordIds(String schemaCode) {
return presenterUtils.getAllRecordIds(schemaCode);
}
public final User wrapUser(Record record) {
return presenterUtils.wrapUser(record);
}
public Roles getCollectionRoles() {
return presenterUtils.getCollectionRoles();
}
public boolean isDeletable(RecordVO entity) {
Record record = presenterService().getRecord(entity.getId());
User user = getCurrentUser();
return recordServices().isLogicallyThenPhysicallyDeletable(record, user);
}
protected NavigationConfig navigationConfig() {
if (config == null) {
ConstellioModulesManagerImpl manager = (ConstellioModulesManagerImpl) appLayerFactory.getModulesManager();
config = manager.getNavigationConfig(view.getCollection());
}
return config;
}
public RMReportBuilderFactories getRmReportBuilderFactories() {
final AppLayerCollectionExtensions extensions = appLayerFactory.getExtensions().forCollection(collection);
final RMModuleExtensions rmModuleExtensions = extensions.forModule(ConstellioRMModule.ID);
return rmModuleExtensions.getReportBuilderFactories();
}
public ContentVersionDataSummary uploadContent(final InputStream inputStream, final boolean handleDeletionOfUnreferencedHashes, final boolean parse, final String fileName) {
return presenterUtils.uploadContent(inputStream, handleDeletionOfUnreferencedHashes, parse, fileName);
}
}