From 5eee834a05c8674c391cfb80a6b3041d0b4ab54a Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Mon, 10 Aug 2020 16:52:50 +0200
Subject: [PATCH] OO-4820: adapt calendar and authentications web service

Adapt calendar web service to not use the identity name, add a new user
authentications web service based on identity key, remove the advanced
properties controller
---
 .../org/olat/_spring/extensionContext.xml     |  24 --
 .../AdvancedPropertiesController.java         | 133 ---------
 .../AdvancedPropertySearchForm.java           | 215 ---------------
 .../properties/PropertiesTableDataModel.java  |  85 ------
 .../admin/properties/_content/searchForm.html |  47 ----
 .../_i18n/LocalStrings_ar.properties          |  25 --
 .../_i18n/LocalStrings_bg.properties          |  24 --
 .../_i18n/LocalStrings_cs.properties          |  24 --
 .../_i18n/LocalStrings_da.properties          |  23 --
 .../_i18n/LocalStrings_de.properties          |  25 --
 .../_i18n/LocalStrings_el.properties          |  25 --
 .../_i18n/LocalStrings_en.properties          |  25 --
 .../_i18n/LocalStrings_es.properties          |  24 --
 .../_i18n/LocalStrings_et_EE.properties       |   6 -
 .../_i18n/LocalStrings_fa.properties          |  23 --
 .../_i18n/LocalStrings_fr.properties          |  25 --
 .../_i18n/LocalStrings_it.properties          |  25 --
 .../_i18n/LocalStrings_jp.properties          |  24 --
 .../_i18n/LocalStrings_lt.properties          |  23 --
 .../_i18n/LocalStrings_nl_NL.properties       |  25 --
 .../_i18n/LocalStrings_pl.properties          |  25 --
 .../_i18n/LocalStrings_pt_BR.properties       |  25 --
 .../_i18n/LocalStrings_pt_PT.properties       |  23 --
 .../_i18n/LocalStrings_ru.properties          |  25 --
 .../_i18n/LocalStrings_sq.properties          |  24 --
 .../_i18n/LocalStrings_zh_CN.properties       |  25 --
 .../_i18n/LocalStrings_zh_TW.properties       |  25 --
 .../restapi/UserCalendarWebService.java       |  25 +-
 .../security/AuthenticationWebService.java    |   3 +-
 .../restapi/UserAuthenticationWebService.java |   9 +-
 .../UserAuthenticationsWebService.java        | 254 +++++++++++++++++
 .../restapi/UserAuthenticationMgmtTest.java   |   3 +-
 .../UserAuthenticationsWebServiceTest.java    | 256 ++++++++++++++++++
 .../java/org/olat/test/AllTestsJunit4.java    |   1 +
 34 files changed, 536 insertions(+), 1037 deletions(-)
 delete mode 100644 src/main/java/org/olat/admin/properties/AdvancedPropertiesController.java
 delete mode 100644 src/main/java/org/olat/admin/properties/AdvancedPropertySearchForm.java
 delete mode 100644 src/main/java/org/olat/admin/properties/PropertiesTableDataModel.java
 delete mode 100644 src/main/java/org/olat/admin/properties/_content/searchForm.html
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ar.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_bg.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_cs.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_da.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_de.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_el.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_en.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_es.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_et_EE.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fa.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fr.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_it.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_jp.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_lt.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_nl_NL.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pl.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_BR.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_PT.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ru.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_sq.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_CN.properties
 delete mode 100644 src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_TW.properties
 create mode 100644 src/main/java/org/olat/user/restapi/UserAuthenticationsWebService.java
 create mode 100644 src/test/java/org/olat/restapi/UserAuthenticationsWebServiceTest.java

diff --git a/src/main/java/org/olat/_spring/extensionContext.xml b/src/main/java/org/olat/_spring/extensionContext.xml
index f759fb5f93d..1748d187e22 100644
--- a/src/main/java/org/olat/_spring/extensionContext.xml
+++ b/src/main/java/org/olat/_spring/extensionContext.xml
@@ -510,30 +510,6 @@
 		</property>
 		<property name="parentTreeNodeIdentifier" value="develParent" /> 
 	</bean>
-			
-		
-		
-		
-		
-		<!-- Devel / Advanced properties -->
-		<bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints">
-			<property name="order" value="7500" />
-			<property name="actionController">	
-				<bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype">
-					<property name="className" value="org.olat.admin.properties.AdvancedPropertiesController"/>
-				</bean>
-			</property>
-			<property name="navigationKey" value="advancedproperties" />
-		<property name="parentTreeNodeIdentifier" value="develParent" /> 
-			<property name="i18nActionKey" value="menu.advancedproperties"/>
-			<property name="i18nDescriptionKey" value="menu.advancedproperties.alt"/>
-			<property name="translationPackage" value="org.olat.admin"/>
-			<property name="extensionPoints">
-				<list>	
-					<value>org.olat.admin.SystemAdminMainController</value>		
-				</list>
-			</property>
-		</bean>	
 
 		<!-- Help module -->
 		<bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints">
diff --git a/src/main/java/org/olat/admin/properties/AdvancedPropertiesController.java b/src/main/java/org/olat/admin/properties/AdvancedPropertiesController.java
deleted file mode 100644
index 46e82745423..00000000000
--- a/src/main/java/org/olat/admin/properties/AdvancedPropertiesController.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.admin.properties;
-
-import java.util.List;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.panel.Panel;
-import org.olat.core.gui.components.table.ColumnDescriptor;
-import org.olat.core.gui.components.table.DefaultColumnDescriptor;
-import org.olat.core.gui.components.table.TableController;
-import org.olat.core.gui.components.table.TableGuiConfiguration;
-import org.olat.core.gui.components.velocity.VelocityContainer;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.controller.BasicController;
-import org.olat.properties.Property;
-import org.olat.properties.PropertyManager;
-
-/**
-*  Description:<br>
-*  is the controller for
-*
-* @author Felix Jost
-*/
-public class AdvancedPropertiesController extends BasicController {
-
-	private Panel myPanel;
-	private AdvancedPropertySearchForm searchForm;
-	private VelocityContainer vcSearchForm;
-	
-	private TableController tableCtr;
-	
-	/**
-	 * caller of this constructor must make sure only olat admins come here
-	 * 
-	 * @param ureq
-	 * @param wControl
-	 */
-	public AdvancedPropertiesController(UserRequest ureq, WindowControl wControl) {
-		super(ureq,wControl);
-		
-		myPanel = new Panel("myPanel");
-		myPanel.addListener(this);
-		
-		searchForm = new AdvancedPropertySearchForm(ureq, wControl);
-		listenTo(searchForm);
-		
-		vcSearchForm = createVelocityContainer("searchForm");
-		vcSearchForm.put("searchForm",searchForm.getInitialComponent());
-		myPanel.setContent(vcSearchForm);
-		putInitialPanel(myPanel);
-	}
-
-	@Override
-	public void event(UserRequest ureq, Component source, Event event) {
-		//
-	}
-
-	@Override
-	public void event(UserRequest ureq, Controller source, Event event) {
-		if (source == searchForm && event == Event.DONE_EVENT) {
-				
-				String resourceTypeName = searchForm.getResourceTypeName();
-				String resourceTypeId = searchForm.getResourceTypeId();
-				Long resTypeId = null;
-				if (resourceTypeId != null && !resourceTypeId.equals("")) resTypeId = Long.valueOf(resourceTypeId);
-				String category = searchForm.getCategory();
-				if (category != null && category.equals("")) category = null;
-				String propertyName = searchForm.getPropertyName();
-				if (propertyName != null && propertyName.equals("")) propertyName = null;
-
-				List<Property> entries = PropertyManager.getInstance().listProperties(searchForm.getIdentity(), null, resourceTypeName, resTypeId, category, propertyName);
-				
-				
-				PropertiesTableDataModel ptdm = new PropertiesTableDataModel(entries);
-
-				TableGuiConfiguration tableConfig = new TableGuiConfiguration();
-				
-				removeAsListenerAndDispose(tableCtr);
-				tableCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator());
-				//use null as listener argument because we are using listenTo(..) from basiccontroller
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.userName", 0, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.resourceTypeName", 1, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.resourceTypeId", 2, null, getLocale(),ColumnDescriptor.ALIGNMENT_RIGHT));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.category", 3, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.name", 4, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.floatValue", 5, null, getLocale(), ColumnDescriptor.ALIGNMENT_RIGHT));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.stringValue", 6, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.longValue", 10, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.textValue", 7, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.creationdate", 8, null, getLocale()));
-				tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.lastmodified", 9, null, getLocale()));
-				tableCtr.setTableDataModel(ptdm);
-				listenTo(tableCtr);
-
-				myPanel.setContent(tableCtr.getInitialComponent());		
-		}
-	}
-	
-	/**
-	 * 
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
-	protected void doDispose() {
-		//
-	}
-}
diff --git a/src/main/java/org/olat/admin/properties/AdvancedPropertySearchForm.java b/src/main/java/org/olat/admin/properties/AdvancedPropertySearchForm.java
deleted file mode 100644
index 88a1babee25..00000000000
--- a/src/main/java/org/olat/admin/properties/AdvancedPropertySearchForm.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.admin.properties;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.olat.admin.user.UserSearchController;
-import org.olat.basesecurity.BaseSecurity;
-import org.olat.basesecurity.events.SingleIdentityChosenEvent;
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.form.flexible.FormItem;
-import org.olat.core.gui.components.form.flexible.FormItemContainer;
-import org.olat.core.gui.components.form.flexible.elements.FormLink;
-import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
-import org.olat.core.gui.components.form.flexible.elements.TextElement;
-import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
-import org.olat.core.gui.components.form.flexible.impl.FormEvent;
-import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
-import org.olat.core.gui.components.link.Link;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
-import org.olat.core.id.Identity;
-import org.olat.properties.PropertyManager;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
-*  Description:<br>
-*
-*
-* @author Alexander Schneider
-*/
-public class AdvancedPropertySearchForm extends FormBasicController {
-	private FormLink userChooser;
-	private TextElement userName;
-	private SingleSelection resourceTypeName;
-	private TextElement resourceTypeId;
-	private TextElement category;
-	private TextElement propertyName;
-	private FormLink searchButton;
-	
-	private String[] theKeys;
-	private String[] theValues;
-	private FormLayoutContainer horizontalLayout;
-	
-	private UserSearchController usc;
-	private Identity identity = null;
-	
-	private CloseableModalController cmc;
-	
-	@Autowired
-	private BaseSecurity securityManager;
-
-	/**
-	 * @param name
-	 */
-	public AdvancedPropertySearchForm(UserRequest ureq, WindowControl wControl) {
-		super(ureq, wControl);
-		
-		PropertyManager pm = PropertyManager.getInstance();
-		List<String> resourceTypeNames = pm.getAllResourceTypeNames();
-		int size = resourceTypeNames.size();
-		theKeys = new String[size+1];
-		theValues = new String[size+1];
-		theKeys[0] = "0";
-		theValues[0] = "";
-		int i = 1;
-		for (Iterator<String> iter = resourceTypeNames.iterator(); iter.hasNext(); i++) {
-			theKeys[i] = Integer.toString(i);
-			theValues[i] = iter.next();
-		}
-		
-		initForm(ureq);
-	}
-
-	@Override
-	protected void formOK(UserRequest ureq) {
-		fireEvent(ureq, Event.DONE_EVENT);
-	}
-	
-	@Override
-	protected boolean validateFormLogic(UserRequest ureq) {
-		
-		int c = 0;
-		
-		if (userName.getValue().length()>0) {
-			c++;
-			identity = securityManager.findIdentityByName(userName.getValue());
-	 		if (identity == null){
-	 					userName.setErrorKey ("error.search.form.nousername", null);
-	 					return false;
-	 		}
-		}
-		
-		if (resourceTypeName.getSelected()>0) c++;
-		if (resourceTypeId.getValue().length()>0) c++;
-		if (category.getValue().length()>0) c++;
-		if (propertyName.getValue().length()>0) c++;
-		
-		if (c==0) {
-			showInfo("error.search.form.notempty");
-			return false;
-		}
-		
-		return true;
-	}
-	
-	@Override
-	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		setFormTitle("header.advancedsearchform");
-		
-		horizontalLayout = FormLayoutContainer.createHorizontalFormLayout("userChooser", getTranslator());
-		formLayout.add(horizontalLayout);
-		
-		horizontalLayout.setLabel("searchform.username", null);
-		userName = uifactory.addTextElement("userName", null, 60, "", horizontalLayout);	
-		userChooser = uifactory.addFormLink("choose", horizontalLayout);
-		
-		resourceTypeName = uifactory.addDropdownSingleselect("resourceTypeName", "searchform.resoursetypename", formLayout, theKeys, theValues, null);
-		resourceTypeId = uifactory.addTextElement("resourceTypeId", "searchform.resourcetypeid", 60, "", formLayout);
-		category = uifactory.addTextElement("category", "searchform.category", 60, "", formLayout);
-		propertyName = uifactory.addTextElement("propertyName", "searchform.propertyname", 60, "", formLayout);
-
-		// Don't use submit button, form should not be marked as dirty since this is
-		// not a configuration form but only a search form (OLAT-5626)
-		searchButton = uifactory.addFormLink("search", formLayout, Link.BUTTON);
-		searchButton.addActionListener(FormEvent.ONCLICK);
-		
-		resourceTypeId.setRegexMatchCheck("\\d*", "error.search.form.onlynumbers");
-	}
-	
-	@Override
-	protected void  formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
-		if (source == userChooser) {
-			usc = new UserSearchController(ureq, getWindowControl(), false);
-			listenTo(usc);
-
-			cmc = new CloseableModalController(
-					getWindowControl(),
-					translate("close"),
-					usc.getInitialComponent()
-			);
-			
-			listenTo(cmc);
-			cmc.activate();
-		} else if (source == searchButton) {
-			source.getRootForm().submit(ureq);			
-		}
-	}
-
-	@Override
-	protected void event(UserRequest ureq, Controller source, Event event) {
-		if(source == usc && event.getCommand().equals("IdentityFound")){
-			SingleIdentityChosenEvent uce = (SingleIdentityChosenEvent) event;
-			identity = uce.getChosenIdentity();
-			userName.setValue(identity.getName());
-			cmc.deactivate();
-		} 
-	}
-	
-	@Override
-	protected void doDispose() {
-		//
-	}
-
-	public String getPropertyName() {
-		return propertyName.getValue();
-	}
-
-	public String getCategory() {
-		return category.getValue();
-	}
-
-	public String getResourceTypeId() {
-		return resourceTypeId.getValue();
-	}
-
-	public String getResourceTypeName() {
-		return theValues[resourceTypeName.getSelected()];
-	}
-
-	public String getUserName() {
-		return userName.getValue();
-	}
-	
-	@Override
-	protected Identity getIdentity() {
-		return identity;
-	}
-}
diff --git a/src/main/java/org/olat/admin/properties/PropertiesTableDataModel.java b/src/main/java/org/olat/admin/properties/PropertiesTableDataModel.java
deleted file mode 100644
index 9790fd53b26..00000000000
--- a/src/main/java/org/olat/admin/properties/PropertiesTableDataModel.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.admin.properties;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.olat.core.gui.components.table.DefaultTableDataModel;
-import org.olat.properties.Property;
-import org.olat.user.UserManager;
-
-/**
-*  Description:<br>
-*
-*
-* @author Alexander Schneider
-*/
-public class PropertiesTableDataModel extends DefaultTableDataModel<Property> {
-
-	private final UserManager userManager;
-	
-	/**
-	 * Default constructor.
-	 */
-	public PropertiesTableDataModel() {
-		this(new ArrayList<Property>());
-	}
-
-	/**
-	 * Initialize table model with objects.
-	 * @param objects
-	 */
-	public PropertiesTableDataModel(List<Property> objects) {
-		super(objects);
-		userManager = UserManager.getInstance();
-	}
-
-	@Override
-	public int getColumnCount() {
-		// resourceTypeName, resourceTypeId, category, name, floatValue, stringValue, textValue
-		return 11;
-	}
-	
-	@Override
-	public final Object getValueAt(int row, int col) {
-		Property p = getObject(row); 
-		switch(col) {
-			case 0: return userManager.getUserDisplayName(p.getIdentity());
-			case 1: return p.getResourceTypeName();
-			case 2: return p.getResourceTypeId();
-			case 3: return p.getCategory();
-			case 4: return p.getName();
-			case 5: return p.getFloatValue();
-			case 6: return p.getStringValue();
-			case 7: return p.getTextValue();
-			case 8: return p.getCreationDate().toString();
-			case 9: return p.getLastModified().toString();
-			case 10: return p.getLongValue();
-			default: return "error";
-		}
-	}
-}
diff --git a/src/main/java/org/olat/admin/properties/_content/searchForm.html b/src/main/java/org/olat/admin/properties/_content/searchForm.html
deleted file mode 100644
index 07941a214f8..00000000000
--- a/src/main/java/org/olat/admin/properties/_content/searchForm.html
+++ /dev/null
@@ -1,47 +0,0 @@
-$r.render("searchForm")
-
-<table class="table table-bordered">
-	<thead>
-		<tr><th>$r.translate("table.header.category")</th><th>$r.translate("table.header.desc")</th></tr>
-	</thead>
-	<tbody>
-		<tr><td>_o3_</td><td>System</td></tr>
-		<tr><td>quot</td><td>quota category</td></tr>
-		<tr><td>rvst</td><td>Resource is visited by a certain user</td></tr>
-		<tr><td>collabtools</td><td>identifies properties concerning Collaboration Tools</td></tr>
-		<tr><td>lgrp</td><td>learning group</td></tr>
-		<tr><td>forumKey</td><td>-</td></tr>
-		<tr><td>mid</td><td>visited message key</td></tr>
-		<tr><td>news</td><td>key for news in a collaboration suite</td></tr>
-	</tbody>
-</table>
-
-<table class="table table-bordered">
-	<thead>
-		<tr><th>$r.translate("table.header.name")</th><th>$r.translate("table.header.desc")</th></tr>
-	</thead>
-	<tbody>
-		<tr><td>InfoMsg</td><td>Info Message</td></tr>
-		<tr><td>maintenanceMessageToken</td><td>Token for maintenance message</td></tr>
-		<tr><td>ATTEMPTS</td><td>-</td></tr>
-		<tr><td>PASSED</td><td>-</td></tr>
-		<tr><td>LOG</td><td>-</td></tr>
-		<tr><td>SCORE</td><td>-</td></tr>
-		<tr><td>hasContactform</td><td>constant used to identify the contact form for a BuddyGroup</td></tr>
-		<tr><td>hasFolder</td><td>constant used to identify the folder for a BuddyGroup</td></tr>
-		<tr><td>hasforum</td><td>constant used to identify the forum for a BuddyGroup</td></tr>
-		<tr><td>hasNews</td><td>constant used to identify the contact form for a BuddyGroup</td></tr>
-		<tr><td>initialEnrollmentDate</td><td>the initial enrollment date will be set only the first time the users enrolls to this node</td></tr>
-		<tr><td>recentEnrollmentDate</td><td>will be changed everytime the user enrolls to this node</td></tr>
-		<tr><td>::DEFAULT::COURSEFOLDERS , <br>
-				::DEFAULT::GROUPS , <br>
-				::DEFAULT::NODEFOLDERS , <br>
-				::DEFAULT::POWERUSERS , <br>
-				::DEFAULT::REPOSITORY , <br>
-				::DEFAULT::USERS
-			</td><td>-</td></tr>
-		<tr><td>/homes/[username] e.g.: /homes/admina</td><td>quota for only one user</td></tr>
-		<tr><td>repoEntry:[id] e.g.: repoEntry:1376277</td><td>-</td></tr>
-		<tr><td>RepositoryEntry:[id] e.g.: RepositoryEntry:1376333</td><td>-</td></tr>							
-	</tbody>
-</table>
\ No newline at end of file
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ar.properties
deleted file mode 100644
index 19d0fb33afa..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ar.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Mon Feb 22 11:04:19 CET 2010
-choose=\u0627\u062E\u062A\u064A\u0627\u0631
-close=\u0625\u063A\u0644\u0627\u0642
-cmd.usersearch=\u0628\u062D\u062B \u0628\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645
-error.search.form.notempty=\u064A\u0631\u062C\u0649 \u0643\u062A\u0627\u0628\u0629 \u062E\u0627\u0646\u0629 \u0648\u0627\u062D\u062F\u0629 \u0639\u0644 \u0627\u0644\u0623\u0642\u0644.
-error.search.form.nousername=\u0644\u0645 \u064A\u062A\u0645 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0645\u0633\u062A\u062E\u062F\u0645 \u0628\u0647\u0630\u0627 \u0627\u0644\u0627\u0633\u0645.
-error.search.form.onlynumbers=\!\u0641\u0642\u0637 \u0623\u0631\u0642\u0627\u0645\u060C \u0645\u0646 \u0641\u0636\u0644\u0643
-header.advancedsearchform=\u0646\u0645\u0648\u0630\u062C \u0627\u0644\u0628\u062D\u062B \u0627\u0644\u0645\u062A\u0642\u062F\u0645
-searchform.category=\u0627\u0644\u0641\u0626\u0629
-searchform.propertyname=\u0627\u0644\u0627\u0633\u0645
-searchform.resourcetypeid=\u0631\u0642\u0645 \u0627\u0644\u0645\u0635\u062F\u0631
-searchform.resoursetypename=\u0627\u0633\u0645 \u0627\u0644\u0645\u0635\u062F\u0631
-searchform.username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645
-table.header.category=\u0627\u0644\u0641\u0626\u0629
-table.header.creationdate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0625\u0646\u0634\u0627\u0621
-table.header.desc=\u0627\u0644\u0648\u0635\u0641
-table.header.floatValue=\u0627\u0644\u0642\u064A\u0645\u0629 \u0627\u0644\u0645\u0646\u0634\u0648\u0631\u0629
-table.header.lastmodified=\u0622\u062E\u0631 \u062A\u0639\u062F\u064A\u0644
-table.header.longValue=\u0642\u064A\u0645\u0629 \u0637\u0648\u064A\u0644\u0629
-table.header.name=\u0627\u0644\u0627\u0633\u0645
-table.header.resourceTypeId=\u0631\u0642\u0645 \u0627\u0644\u0646\u0648\u0639
-table.header.resourceTypeName=\u0627\u0644\u0646\u0648\u0639
-table.header.stringValue=\u0642\u064A\u0645\u0629 \u0645\u062A\u0633\u0644\u0633\u0644\u0629
-table.header.textValue=\u0642\u064A\u0645\u0629 \u0627\u0644\u0646\u0635
-table.header.userName=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_bg.properties
deleted file mode 100644
index 1e66132ad07..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_bg.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Fri Aug 28 04:34:46 CEST 2009
-close=\u0417\u0430\u0442\u0432\u043E\u0440\u0435\u0442\u0435
-cmd.usersearch=\u0422\u044A\u0440\u0441\u0435\u0442\u0435 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435
-error.search.form.notempty=\u041C\u043E\u043B\u044F, \u043F\u043E\u043F\u044A\u043B\u043D\u0435\u0442\u0435 \u043F\u043E\u043D\u0435 \u0435\u0434\u043D\u043E \u043E\u0442 \u0441\u044A\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438\u0442\u0435 \u043F\u043E\u043B\u0435\u0442\u0430.
-error.search.form.nousername=\u041D\u0435 \u0435 \u043D\u0430\u043C\u0435\u0440\u0435\u043D \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B \u0441 \u0442\u043E\u0432\u0430 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435.
-error.search.form.onlynumbers=\u0421\u0430\u043C\u043E \u0446\u0438\u0444\u0440\u0438, \u043C\u043E\u043B\u044F\!
-header.advancedsearchform=\u0424\u043E\u0440\u043C\u0430 \u0437\u0430 \u0442\u044A\u0440\u0441\u0435\u043D\u0435 \u0437\u0430 \u043D\u0430\u043F\u0440\u0435\u0434\u043D\u0430\u043B\u0438
-searchform.category=\u041A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044F
-searchform.propertyname=\u0418\u043C\u0435
-searchform.resourcetypeid=\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u043E\u043D\u0435\u043D \u043D\u043E\u043C\u0435\u0440 \u043D\u0430 \u0432\u0438\u0434 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B
-searchform.resoursetypename=\u0418\u043C\u0435 \u043D\u0430 \u0432\u0438\u0434 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B
-searchform.username=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435
-table.header.category=\u041A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044F
-table.header.creationdate=\u0414\u0430\u0442\u0430 \u043D\u0430 \u0441\u044A\u0437\u0434\u0430\u0432\u0430\u043D\u0435
-table.header.desc=\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435
-table.header.floatValue=Float value
-table.header.lastmodified=\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u043E \u043F\u0440\u043E\u043C\u0435\u043D\u0435\u043D
-table.header.longValue=\u0414\u044A\u043B\u0433\u0430 \u0441\u0442\u043E\u0439\u043D\u043E\u0441\u0442
-table.header.name=\u0418\u043C\u0435
-table.header.resourceTypeId=\u041D\u0430\u043F\u0438\u0448\u0435\u0442\u0435 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u043E\u043D\u0435\u043D \u043D\u043E\u043C\u0435\u0440
-table.header.resourceTypeName=\u0412\u0438\u0434
-table.header.stringValue=String value
-table.header.textValue=\u0422\u0435\u043A\u0441\u0442\u043E\u0432\u0430 \u0441\u0442\u043E\u0439\u043D\u043E\u0441\u0442
-table.header.userName=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_cs.properties
deleted file mode 100644
index e5975bda093..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_cs.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Mon Mar 02 09:54:13 CET 2009
-close=Zav\u0159\u00EDt
-cmd.usersearch=Naj\u00EDt u\u017Eivatelsk\u00E9 jm\u00E9no
-error.search.form.notempty=Pros\u00EDm, vypl\u0148te alespo\u0148 jedno z dostupn\u00FDch pol\u00ED.
-error.search.form.nousername=Nenalezen \u017E\u00E1dn\u00FD u\u017Eivatel s t\u00EDmto u\u017Eivatelsk\u00FDm jm\u00E9nem. Zkuste znovu.
-error.search.form.onlynumbers=Pouze \u010D\u00EDsla\!
-header.advancedsearchform=Vyhled\u00E1n\u00ED poko\u010Dil\u00FDch vlastnost\u00ED
-searchform.category=Kategorie
-searchform.propertyname=Jm\u00E9no
-searchform.resourcetypeid=ID typu zdroje
-searchform.resoursetypename=Jm\u00E9no typu zdroje
-searchform.username=U\u017Eivatelsk\u00E9 jm\u00E9no
-table.header.category=Kategorie
-table.header.creationdate=Datum vytvo\u0159en\u00ED
-table.header.desc=Popis
-table.header.floatValue=Float hodnota
-table.header.lastmodified=Posledn\u00ED zm\u011Bna
-table.header.longValue=Long hodnota
-table.header.name=Jm\u00E9no
-table.header.resourceTypeId=ID Typu
-table.header.resourceTypeName=Typ
-table.header.stringValue=String hodnota
-table.header.textValue=Text hodnota
-table.header.userName=U\u017Eivatelsk\u00E9 jm\u00E9no
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_da.properties
deleted file mode 100644
index 76b30a67180..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_da.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#Mon Mar 02 09:54:08 CET 2009
-close=Luk vindue
-cmd.usersearch=S\u00F8g efter brugernavn
-error.search.form.notempty=Udfyld venligst mindst et af de tilg\u00E6ngelige felter.
-error.search.form.nousername=Ingen bruger fundet med dette brugernavn
-error.search.form.onlynumbers=Kun tal, tak\!
-header.advancedsearchform=Formular til s\u00F8gning efter avancerede indstillinger
-searchform.category=Kategori
-searchform.propertyname=Navn
-searchform.resourcetypeid=Ressource type ID
-searchform.resoursetypename=Ressource type navn
-searchform.username=Brugernavn
-table.header.category=Kategori
-table.header.creationdate=Oprettelsesdato
-table.header.floatValue=Kommatal
-table.header.lastmodified=Sidst \u00E6ndret
-table.header.longValue=Heltalsv\u00E6rdi
-table.header.name=Navn
-table.header.resourceTypeId=Type ID
-table.header.resourceTypeName=Type
-table.header.stringValue=Strengv\u00E6rdi
-table.header.textValue=Tekstv\u00E6rdi
-table.header.userName=Brugernavn
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_de.properties
deleted file mode 100644
index c9650e82b1e..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_de.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Mon Mar 02 09:54:03 CET 2009
-close=Schliessen
-cmd.usersearch=Benutzername suchen
-error.search.form.notempty=Bitte mindestends ein Feld ausf\u00FCllen.
-error.search.form.nousername=Es konnte kein Benutzer mit diesem Benutzernamen gefunden werden.
-error.search.form.onlynumbers=Bitte nur Zahlen\!
-header.advancedsearchform=Erweitertes property Suchformular
-searchform.category=Kategorie
-searchform.propertyname=Name
-searchform.resourcetypeid=Resource Type Id
-searchform.resoursetypename=Resource Type Name
-searchform.username=Benutzername
-table.header.category=Kategorie
-table.header.creationdate=creationDate
-table.header.desc=Beschreibung
-table.header.floatValue=floatValue
-table.header.lastmodified=lastModified
-table.header.longValue=longValue
-table.header.name=Name
-table.header.resourceTypeId=TypeID
-table.header.resourceTypeName=Type
-table.header.stringValue=stringValue
-table.header.textValue=textValue
-table.header.userName=Benutzername
-choose = Auswahl
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_el.properties
deleted file mode 100644
index 3f9d7e5f547..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_el.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Fri Mar 05 11:44:47 CET 2010
-choose=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
-close=\u039A\u03BB\u03B5\u03AF\u03C3\u03B9\u03BC\u03BF
-cmd.usersearch=\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BF\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7
-error.search.form.notempty=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03C3\u03C5\u03BC\u03C0\u03BB\u03B7\u03C1\u03CE\u03C3\u03C4\u03B5 \u03C4\u03BF\u03C5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF \u03AD\u03BD\u03B1 \u03C0\u03B5\u03B4\u03AF\u03BF.
-error.search.form.nousername=\u0394\u03B5\u03BD \u03B2\u03C1\u03AD\u03B8\u03B7\u03BA\u03B5 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03BC\u03B5 \u03B1\u03C5\u03C4\u03CC \u03C4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7.
-error.search.form.onlynumbers=\u039C\u03CC\u03BD\u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03CD\u03C2
-header.advancedsearchform=\u0395\u03BE\u03B5\u03B9\u03B4\u03B9\u03BA\u03B5\u03C5\u03BC\u03AD\u03BD\u03B7 \u03C6\u03CC\u03C1\u03BC\u03B1 \u03B1\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7\u03C2 \u03B9\u03B4\u03B9\u03BF\u03C4\u03AE\u03C4\u03C9\u03BD
-searchform.category=\u039A\u03B1\u03C4\u03B7\u03B3\u03BF\u03C1\u03AF\u03B1
-searchform.propertyname=\u038C\u03BD\u03BF\u03BC\u03B1
-searchform.resourcetypeid=ID \u03C4\u03CD\u03C0\u03BF\u03C5 \u03C0\u03CC\u03C1\u03BF\u03C5
-searchform.resoursetypename=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C4\u03CD\u03C0\u03BF\u03C5 \u03C0\u03CC\u03C1\u03BF\u03C5
-searchform.username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7
-table.header.category=\u039A\u03B1\u03C4\u03B7\u03B3\u03BF\u03C1\u03AF\u03B1
-table.header.creationdate=\u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1 \u03B4\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1\u03C2
-table.header.desc=\u03A0\u03B5\u03C1\u03B9\u03B3\u03C1\u03B1\u03C6\u03AE
-table.header.floatValue=\u03A4\u03B9\u03BC\u03AE Float
-table.header.lastmodified=\u03A4\u03B5\u03BB\u03B5\u03C5\u03C4\u03B1\u03AF\u03B1 \u03C0\u03BF\u03C5 \u03C4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03B9\u03AE\u03B8\u03B7\u03BA\u03B5
-table.header.longValue=\u03A4\u03B9\u03BC\u03AE Long
-table.header.name=\u038C\u03BD\u03BF\u03BC\u03B1
-table.header.resourceTypeId=ID \u03C4\u03CD\u03C0\u03BF\u03C5
-table.header.resourceTypeName=\u03A4\u03CD\u03C0\u03BF\u03C2
-table.header.stringValue=\u03A4\u03B9\u03BC\u03AE String
-table.header.textValue=\u03A4\u03B9\u03BC\u03AE Text
-table.header.userName=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_en.properties
deleted file mode 100644
index f8a408b4cba..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_en.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Mon Feb 01 17:51:13 CET 2010
-choose=Selection
-close=Close
-cmd.usersearch=Search user name
-error.search.form.notempty=Please fill in at least one field.
-error.search.form.nousername=No user found with this user name.
-error.search.form.onlynumbers=Only figures, please\!
-header.advancedsearchform=Advanced property search form
-searchform.category=Category
-searchform.propertyname=Name
-searchform.resourcetypeid=Resource type ID
-searchform.resoursetypename=Resource type name
-searchform.username=User name
-table.header.category=Category
-table.header.creationdate=Creation date
-table.header.desc=Description
-table.header.floatValue=Float value
-table.header.lastmodified=Last modified
-table.header.longValue=Long value
-table.header.name=Name
-table.header.resourceTypeId=Type ID
-table.header.resourceTypeName=Type
-table.header.stringValue=String value
-table.header.textValue=Text value
-table.header.userName=User name
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_es.properties
deleted file mode 100644
index 18fbe9495a0..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_es.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Mon Mar 02 09:54:20 CET 2009
-close=cerrar
-cmd.usersearch=Buscar nombre de usuario
-error.search.form.notempty=Por favor rellena al menos uno de las casillas disponibles
-error.search.form.nousername=No se encontr\u00F3 ning\u00FAn usuario con ese nombre. Por favor int\u00E9ntalo de nuevo.
-error.search.form.onlynumbers=\u00A1Por favor, s\u00F3lo n\u00FAmeros\!
-header.advancedsearchform=B\u00FAsqueda avanzada de propiedades
-searchform.category=Categor\u00EDa
-searchform.propertyname=Nombre
-searchform.resourcetypeid=ID del tipo de recurso
-searchform.resoursetypename=Nombre del tipo de recurso
-searchform.username=Nombre de usuario
-table.header.category=Categor\u00EDa
-table.header.creationdate=Fecha de creaci\u00F3n
-table.header.desc=Descripci\u00F3n
-table.header.floatValue=floatValue
-table.header.lastmodified=\u00DAltima modificaci\u00F3n
-table.header.longValue=longValue
-table.header.name=Nombre
-table.header.resourceTypeId=Tipo ID
-table.header.resourceTypeName=Tipo
-table.header.stringValue=stringValue
-table.header.textValue=textValue
-table.header.userName=Nombre de usuario
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_et_EE.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_et_EE.properties
deleted file mode 100644
index 61e4e85b1db..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_et_EE.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Sat Oct 24 23:36:29 CEST 2009
-table.header.desc=Kirjeldus
-table.header.lastmodified=Viimati muudetud
-table.header.name=Nimi
-table.header.resourceTypeName=T\u00FC\u00FCp
-table.header.userName=Kasutajanimi
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fa.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fa.properties
deleted file mode 100644
index a556e25b362..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fa.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#Mon Mar 02 09:54:12 CET 2009
-close=\u0628\u0633\u062A\u0646
-cmd.usersearch=\u062C\u0633\u062A\u062C\u0648\u06CC \u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631\u06CC
-error.search.form.notempty=\u0644\u0637\u0641\u0627 \u062D\u062F\u0627\u0642\u0644 \u06CC\u06A9\u06CC \u0627\u0632 \u0641\u06CC\u0644\u062F \u0647\u0627\u06CC \u0645\u0648\u062C\u0648\u062F \u0631\u0627 \u067E\u0631 \u06A9\u0646\u06CC\u062F.
-error.search.form.nousername=\u06A9\u0627\u0631\u0628\u0631\u06CC \u0628\u0627 \u0627\u06CC\u0646 \u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631\u06CC \u06CC\u0627\u0641\u062A \u0646\u0634\u062F
-error.search.form.onlynumbers=\u0641\u0642\u0637 \u0634\u0645\u0627\u0631\u0647 \u0648\u0627\u0631\u062F \u06A9\u0646\u06CC\u062F
-header.advancedsearchform=\u0641\u0631\u0645 \u062C\u0633\u062A\u062C\u0648\u06CC \u0645\u0634\u062E\u0635\u0627\u062A \u067E\u06CC\u0634\u0631\u0641\u062A\u0647
-searchform.category=\u0637\u0628\u0642\u0647
-searchform.propertyname=\u0646\u0627\u0645
-searchform.resourcetypeid=Resource type ID
-searchform.resoursetypename=Resource type name
-searchform.username=\u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631\u06CC
-table.header.category=\u0637\u0628\u0642\u0647
-table.header.creationdate=\u062A\u0627\u0631\u06CC\u062E \u0627\u06CC\u062C\u0627\u062F
-table.header.floatValue=Float value
-table.header.lastmodified=\u0622\u062E\u0631\u06CC\u0646 \u0648\u06CC\u0631\u0627\u06CC\u0634
-table.header.longValue=Long value
-table.header.name=\u0646\u0627\u0645
-table.header.resourceTypeId=Type ID
-table.header.resourceTypeName=Type
-table.header.stringValue=String value
-table.header.textValue=Text value
-table.header.userName=\u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631\u06CC
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fr.properties
deleted file mode 100644
index de669b8ffab..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_fr.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Tue Feb 09 01:34:15 CET 2010
-choose=S\u00E9lection
-close=Fermer
-cmd.usersearch=Rechercher nom d'utilisateur
-error.search.form.notempty=Veuillez remplir au minimum un champ s.v.p.
-error.search.form.nousername=Aucun utilisateur avec ce nom n'a \u00E9t\u00E9 trouv\u00E9.
-error.search.form.onlynumbers=Uniquement des chiffres s.v.p.\!
-header.advancedsearchform=Formulaire de recherche de propri\u00E9t\u00E9s \u00E9largi 
-searchform.category=Cat\u00E9gorie
-searchform.propertyname=Nom
-searchform.resourcetypeid=Id du type de ressource
-searchform.resoursetypename=Nom du type de ressource
-searchform.username=Nom d'utilisateur
-table.header.category=Cat\u00E9gorie
-table.header.creationdate=Date de cr\u00E9ation
-table.header.desc=Description
-table.header.floatValue=floatValue
-table.header.lastmodified=Derni\u00E8re modification
-table.header.longValue=longValue
-table.header.name=Nom
-table.header.resourceTypeId=TypeID
-table.header.resourceTypeName=Type
-table.header.stringValue=stringValue
-table.header.textValue=textValue
-table.header.userName=Nom d'utilisateur
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_it.properties
deleted file mode 100644
index 71c3477c366..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_it.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Thu Feb 09 09:17:58 CET 2017
-choose=Selezione
-close=Chiudere
-cmd.usersearch=Cercare nome d'utente
-error.search.form.notempty=Compili almeno una casella.
-error.search.form.nousername=Non \u00E8 stato trovato alcun utente con questo nome.
-error.search.form.onlynumbers=Solo cifre, p.f.
-header.advancedsearchform=Modulo di ricerca esteso per attributi 
-searchform.category=Categoria
-searchform.propertyname=Nome
-searchform.resourcetypeid=Id del tipo di risorsa
-searchform.resoursetypename=Nome del tipo di risorsa
-searchform.username=Nome utente
-table.header.category=Categoria
-table.header.creationdate=creationDate
-table.header.desc=Descrizione
-table.header.floatValue=floatValue
-table.header.lastmodified=lastModified
-table.header.longValue=longValue
-table.header.name=Nome
-table.header.resourceTypeId=Id del tipo
-table.header.resourceTypeName=Tipo
-table.header.stringValue=stringValue
-table.header.textValue=textValue
-table.header.userName=Nome utente
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_jp.properties
deleted file mode 100644
index c576f715edd..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_jp.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Sun May 09 23:13:30 CEST 2010
-choose=\u9078\u629E
-close=\u9589\u3058\u308B
-cmd.usersearch=\u30E6\u30FC\u30B6\u540D\u3092\u691C\u7D22\u3059\u308B
-error.search.form.notempty=\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u5229\u7528\u53EF\u80FD\u306A\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
-error.search.form.nousername=\u3053\u306E\u30E6\u30FC\u30B6\u540D\u306E\u30E6\u30FC\u30B6\u306F\u3001\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002
-error.search.form.onlynumbers=\u6570\u5B57\u306E\u307F\u3067\u3059\u3001\u304A\u9858\u3044\u3057\u307E\u3059\!
-header.advancedsearchform=\u62E1\u5F35\u30D7\u30ED\u30D1\u30C6\u30A3\u691C\u7D22\u30D5\u30A9\u30FC\u30E0
-searchform.category=\u30AB\u30C6\u30B4\u30EA
-searchform.propertyname=\u6C0F\u540D
-searchform.resourcetypeid=\u30EA\u30BD\u30FC\u30B9\u30BF\u30A4\u30D7ID
-searchform.resoursetypename=\u30EA\u30BD\u30FC\u30B9\u30BF\u30A4\u30D7\u540D
-searchform.username=\u30E6\u30FC\u30B6\u540D
-table.header.category=\u30AB\u30C6\u30B4\u30EA
-table.header.creationdate=\u4F5C\u6210\u65E5
-table.header.desc=\u8AAC\u660E
-table.header.floatValue=\u6D6E\u52D5\u5024
-table.header.lastmodified=\u6700\u7D42\u66F4\u65B0\u65E5
-table.header.name=\u540D\u79F0
-table.header.resourceTypeId=\u30BF\u30A4\u30D7ID
-table.header.resourceTypeName=\u30BF\u30A4\u30D7
-table.header.stringValue=\u30B9\u30C8\u30EA\u30F3\u30B0\u5024
-table.header.textValue=\u30C6\u30AD\u30B9\u30C8\u5024
-table.header.userName=\u30E6\u30FC\u30B6\u540D
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_lt.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_lt.properties
deleted file mode 100644
index e7d73b20c23..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_lt.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#Mon Mar 02 09:54:01 CET 2009
-close=U\u017Edaryti
-cmd.usersearch=Ie\u0161koti naudotojo vardo
-error.search.form.notempty=Pra\u0161ome u\u017Epildyti bent viena i\u0161 lauk\u0173.
-error.search.form.nousername=Tokiu vardu naudotojo n\u0117ra.
-error.search.form.onlynumbers=\u012Eveskite tik skai\u010Dius\!
-header.advancedsearchform=I\u0161pl\u0117stin\u0117 savyb\u0117s paie\u0161kos forma
-searchform.category=Kategorija
-searchform.propertyname=Pavadinimas
-searchform.resourcetypeid=Resurs\u0173 tipo ID
-searchform.resoursetypename=Resurs\u0173 tipo pavadinimas
-searchform.username=Naudotojo vardas
-table.header.category=Kategorija
-table.header.creationdate=Suk\u016Brimo data
-table.header.floatValue=Reik\u0161m\u0117 su slenkan\u010Diu kableliu
-table.header.lastmodified=Paskutinio pakeitimo data
-table.header.longValue="Long" formato reik\u0161m\u0117
-table.header.name=Pavadinimas
-table.header.resourceTypeId=Tipo ID
-table.header.resourceTypeName=Tipas
-table.header.stringValue=Simbolin\u0117 reik\u0161m\u0117
-table.header.textValue=Tekstin\u0117 reik\u0161m\u0117
-table.header.userName=Naudotojo vardas
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_nl_NL.properties
deleted file mode 100644
index e3050e1a432..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_nl_NL.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Thu Sep 08 16:42:42 CEST 2011
-choose=Selectie
-close=Sluiten
-cmd.usersearch=Zoek gebruikersnaam
-error.search.form.notempty=Gelieve ten minste \u00E9\u00E9n veld in te vullen.
-error.search.form.nousername=Geen gebruikers gevonden met deze gebruikersnaam.
-error.search.form.onlynumbers=Gelieve alleen numerieke gegevens\!
-header.advancedsearchform=Geavanceerd property zoek formulier
-searchform.category=Categorie
-searchform.propertyname=Naam
-searchform.resourcetypeid=Resource type ID
-searchform.resoursetypename=Resource type name
-searchform.username=Gebruikersnaam
-table.header.category=Categorie
-table.header.creationdate=Aanmaakdatum
-table.header.desc=Beschrijving
-table.header.floatValue=Float value
-table.header.lastmodified=Last modified
-table.header.longValue=Long value
-table.header.name=Name
-table.header.resourceTypeId=Type ID
-table.header.resourceTypeName=Type
-table.header.stringValue=String value
-table.header.textValue=Text value
-table.header.userName=Gebruikersnaam
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pl.properties
deleted file mode 100644
index c862e721461..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pl.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Sun Mar 14 22:31:02 CET 2010
-choose=Wyb\u00F3r
-close=Zamknij
-cmd.usersearch=Wyszukaj nazw\u0119 u\u017Cytkownika
-error.search.form.notempty=Prosz\u0119 uzupe\u0142ni\u0107 co najmniej jedno z dost\u0119pnych p\u00F3l\!
-error.search.form.nousername=Nie znaleziono u\u017Cytkownika o takiej nazwie. Prosz\u0119 spr\u00F3bowa\u0107 jeszcze raz...
-error.search.form.onlynumbers=Tylko liczby\!
-header.advancedsearchform=Zaawansowane wyszukiwanie w\u0142a\u015Bciwo\u015Bci
-searchform.category=Kategoria
-searchform.propertyname=Nazwa
-searchform.resourcetypeid=ID typu zasobu
-searchform.resoursetypename=Nazwa typu zasobu
-searchform.username=Nazwa u\u017Cytkownika
-table.header.category=Kategoria
-table.header.creationdate=Data utworzenia
-table.header.desc=Opis
-table.header.floatValue=Warto\u015B\u0107 liczbowa (float)
-table.header.lastmodified=Ostatnia modyfikacja
-table.header.longValue=Warto\u015B\u0107 liczbowa (long)
-table.header.name=Nazwa
-table.header.resourceTypeId=ID typu
-table.header.resourceTypeName=Typ
-table.header.stringValue=Warto\u015B\u0107 (ci\u0105g znak\u00F3w)
-table.header.textValue=Tekst
-table.header.userName=Nazwa u\u017Cytkownika
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_BR.properties
deleted file mode 100644
index 641900b0bef..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_BR.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Wed Jun 09 14:45:17 CEST 2010
-choose=Sele\u00E7\u00E3o
-close=Fechar
-cmd.usersearch=Buscar nome do usu\u00E1rio
-error.search.form.notempty=Favor completar no m\u00EDnimo um dos campos dispon\u00EDveis.
-error.search.form.nousername=Nenhum usu\u00E1rio encontrado com este nome. 
-error.search.form.onlynumbers=Somente figuras, por favor\! 
-header.advancedsearchform=Tela de busca propriedades avan\u00E7adas
-searchform.category=Categoria
-searchform.propertyname=Nome
-searchform.resourcetypeid=ID do tipo de recurso
-searchform.resoursetypename=Nome do tipo de recurso
-searchform.username=Nome do usu\u00E1rio
-table.header.category=Categoria
-table.header.creationdate=Data de cria\u00E7\u00E3o
-table.header.desc=Descri\u00E7\u00E3o
-table.header.floatValue=Valor tipo float
-table.header.lastmodified=\u00DAltima modifica\u00E7\u00E3o
-table.header.longValue=Valor tipo long
-table.header.name=Nome
-table.header.resourceTypeId=Digitar ID
-table.header.resourceTypeName=Digitar
-table.header.stringValue=Valor tipo string
-table.header.textValue=Valor tipo text
-table.header.userName=Nome do usu\u00E1rio
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_PT.properties
deleted file mode 100644
index 36d2a3a3333..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_pt_PT.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#Mon Mar 02 09:54:04 CET 2009
-close=Fechar
-cmd.usersearch=Buscar nome do usu\u00E1rio
-error.search.form.notempty=Favor completar no m\u00EDnimo um dos campos dispon\u00EDveis.
-error.search.form.nousername=Nenhum usu\u00E1rio encontrado com este nome. 
-error.search.form.onlynumbers=Somente figuras, por favor\! 
-header.advancedsearchform=Tela de busca propriedades avan\u00E7adas
-searchform.category=Categoria
-searchform.propertyname=Nome
-searchform.resourcetypeid=ID do tipo de recurso
-searchform.resoursetypename=Nome do tipo de recurso
-searchform.username=Nome do usu\u00E1rio
-table.header.category=Categoria
-table.header.creationdate=Data de cria\u00E7\u00E3o
-table.header.floatValue=Valor tipo float
-table.header.lastmodified=\u00DAltima modifica\u00E7\u00E3o
-table.header.longValue=Valor tipo long
-table.header.name=Nome
-table.header.resourceTypeId=Digitar ID
-table.header.resourceTypeName=Digitar
-table.header.stringValue=Valor tipo string
-table.header.textValue=Valor tipo text
-table.header.userName=Nome do usu\u00E1rio
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ru.properties
deleted file mode 100644
index 2d89281e4f4..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_ru.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Sun Jan 24 08:57:57 CET 2010
-choose=\u0412\u044B\u0431\u043E\u0440
-close=\u0417\u0430\u043A\u0440\u044B\u0442\u044C
-cmd.usersearch=\u0418\u0441\u043A\u0430\u0442\u044C \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F
-error.search.form.notempty=\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430.
-error.search.form.nousername=\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F, \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E \u0412\u0430\u0448\u0435\u043C\u0443 \u0437\u0430\u043F\u0440\u043E\u0441\u0443, \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E.
-error.search.form.onlynumbers=\u0422\u043E\u043B\u043A\u043E \u0447\u0438\u0441\u043B\u0430, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430\!
-header.advancedsearchform=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u043D\u044B\u0439 \u043F\u043E\u0438\u0441\u043A 
-searchform.category=\u041A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044F
-searchform.propertyname=\u0418\u043C\u044F
-searchform.resourcetypeid=Id \u0442\u0438\u043F\u0430 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\u0430
-searchform.resoursetypename=\u0418\u043C\u044F \u0442\u0438\u043F\u0430 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\u0430
-searchform.username=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F
-table.header.category=\u041A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044F
-table.header.creationdate=\u0414\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F
-table.header.desc=\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435
-table.header.floatValue=floatValue
-table.header.lastmodified=\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F
-table.header.longValue=longValue
-table.header.name=\u0418\u043C\u044F
-table.header.resourceTypeId=ID \u0442\u0438\u043F\u0430
-table.header.resourceTypeName=\u0422\u0438\u043F
-table.header.stringValue=stringValue
-table.header.textValue=textValue
-table.header.userName=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_sq.properties
deleted file mode 100644
index fd95434e1d4..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_sq.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Mon Mar 02 09:54:11 CET 2009
-close=mbyll
-cmd.usersearch=K\u00EBrko em\u00EBr t\u00EB shfryt\u00EBzuesit
-error.search.form.notempty=Ju lutmi plot\u00EBsoni t\u00EB pakt\u00EBn nj\u00EB nga fushat e gatshme.
-error.search.form.nousername=Nuk u gjet ndonj\u00EB shfryt\u00EBzues me k\u00EBt\u00EB em\u00EBr, Ju lutemi provoni p\u00EBrs\u00EBri.
-error.search.form.onlynumbers=Ju lutemi, vet\u00EBm numra\!
-header.advancedsearchform=K\u00EBrkimi i tipareve t\u00EB avancuara
-searchform.category=Kategoria
-searchform.propertyname=Emri
-searchform.resourcetypeid=ID-ja e llojit t\u00EB burimit
-searchform.resoursetypename=Emri i lloji t\u00EB burimit
-searchform.username=Shfryt\u00EBzuesi
-table.header.category=Kategoria
-table.header.creationdate=Data e krijimit
-table.header.desc=P\u00EBrshkrimi
-table.header.floatValue=Vlera Float
-table.header.lastmodified=Ndryshuar p\u00EBr her\u00EB t\u00EB fundit
-table.header.longValue=Vlera Long
-table.header.name=Emri
-table.header.resourceTypeId=ID-ja e llojit
-table.header.resourceTypeName=Lloji
-table.header.stringValue=Vlera String
-table.header.textValue=Vlera Text
-table.header.userName=Shfryt\u00EBzuesi
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_CN.properties
deleted file mode 100644
index 830713e1631..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_CN.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Fri Feb 12 08:38:52 CET 2010
-choose=\u9009\u62E9
-close=\u5173\u95ED
-cmd.usersearch=\u641C\u7D22\u7528\u6237\u540D
-error.search.form.notempty=\u8BF7\u81F3\u5C11\u586B\u5199\u4E00\u9879. 
-error.search.form.nousername=\u672A\u627E\u5230\u8BE5\u7528\u6237.
-error.search.form.onlynumbers=\u53EA\u80FD\u586B\u5199\u6570\u5B57\uFF01
-header.advancedsearchform=\u9AD8\u7EA7\u641C\u7D22
-searchform.category=\u76EE\u5F55
-searchform.propertyname=\u540D\u79F0
-searchform.resourcetypeid=\u8D44\u6E90\u7C7B\u578BID
-searchform.resoursetypename=\u8D44\u6E90\u7C7B\u578B
-searchform.username=\u7528\u6237\u540D
-table.header.category=\u7C7B\u522B
-table.header.creationdate=\u521B\u5EFA\u65E5\u671F
-table.header.desc=\u63CF\u8FF0\u4FE1\u606F
-table.header.floatValue=\u6D6E\u70B9\u578B
-table.header.lastmodified=\u6700\u540E\u4FEE\u6539
-table.header.longValue=\u957F\u6574\u578B
-table.header.name=\u540D\u79F0
-table.header.resourceTypeId=\u7C7B\u578BID
-table.header.resourceTypeName=\u7C7B\u578B
-table.header.stringValue=\u5B57\u7B26\u4E32\u578B
-table.header.textValue=\u6587\u672C\u578B
-table.header.userName=\u7528\u6237\u540D
diff --git a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_TW.properties
deleted file mode 100644
index 55dcff5d76d..00000000000
--- a/src/main/java/org/olat/admin/properties/_i18n/LocalStrings_zh_TW.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#Sun Jan 24 09:00:07 CET 2010
-choose=\u9078\u64C7
-close=\u95DC\u9589
-cmd.usersearch=\u641C\u5C0B\u4F7F\u7528\u8005\u540D\u7A31
-error.search.form.notempty=\u8ACB\u81F3\u5C11\u586B\u5BEB\u4E00\u6B04\u3002 
-error.search.form.nousername=\u627E\u4E0D\u5230\u8A72\u4F7F\u7528\u8005\u540D\u7A31\u3002
-error.search.form.onlynumbers=\u53EA\u80FD\u586B\u5BEB\u6578\u5B57\uFF01
-header.advancedsearchform=\u9032\u968E\u5C6C\u6027\u641C\u5C0B\u8868\u55AE
-searchform.category=\u5206\u985E
-searchform.propertyname=\u540D\u7A31
-searchform.resourcetypeid=\u8CC7\u6E90\u985E\u578B ID
-searchform.resoursetypename=\u8CC7\u6E90\u985E\u578B\u540D\u7A31
-searchform.username=\u4F7F\u7528\u8005\u540D\u7A31
-table.header.category=\u5206\u985E
-table.header.creationdate=\u5EFA\u7ACB\u65E5\u671F
-table.header.desc=\u8AAA\u660E
-table.header.floatValue=\u6D6E\u9EDE\u6578\u503C
-table.header.lastmodified=\u6700\u5F8C\u4FEE\u6539\u6642\u9593
-table.header.longValue=\u9577\u6574\u6578\u503C
-table.header.name=\u540D\u7A31
-table.header.resourceTypeId=\u985E\u578B ID
-table.header.resourceTypeName=\u985E\u578B
-table.header.stringValue=\u5B57\u4E32\u503C
-table.header.textValue=\u6587\u5B57\u503C
-table.header.userName=\u4F7F\u7528\u8005\u540D\u7A31
diff --git a/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java b/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
index da7ac14f8f0..100a7673cc0 100644
--- a/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
+++ b/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
@@ -155,11 +155,21 @@ public class UserCalendarWebService {
 		if(ureq.getIdentity() == null || !ureq.getUserSession().isAuthenticated()) {
 			throw new WebApplicationException(Response.serverError().status(Status.UNAUTHORIZED).build());
 		}
-		if (!ureq.getIdentity().getKey().equals(identityKey) && !isManager(identityKey, httpRequest)) {
+		
+		Identity identity;
+		if(ureq.getIdentity().getKey().equals(identityKey)) {
+			identity = ureq.getIdentity();
+		} else if (!ureq.getIdentity().getKey().equals(identityKey) && !isManager(identityKey, httpRequest)) {
 			throw new WebApplicationException(Response.serverError().status(Status.UNAUTHORIZED).build());
+		} else {
+			identity = securityManager.loadIdentityByKey(identityKey);
+		}
+		
+		if(identity == null) {
+			throw new WebApplicationException(Response.serverError().status(Status.NOT_FOUND).build());
 		}
 		
-		KalendarRenderWrapper calendar = getCalendar(ureq, calendarId);
+		KalendarRenderWrapper calendar = getCalendar(ureq, identity, calendarId);
 		if(calendar == null) {
 			throw new WebApplicationException(Response.serverError().status(Status.NOT_FOUND).build());
 		}
@@ -210,7 +220,7 @@ public class UserCalendarWebService {
 		return processEvents(events, onlyFuture, start, limit, httpRequest, request);
 	}
 	
-	private KalendarRenderWrapper getCalendar(UserRequest ureq, String calendarId) {
+	private KalendarRenderWrapper getCalendar(UserRequest ureq, Identity identity, String calendarId) {
 		int typeIndex = calendarId.indexOf('_');
 		if(typeIndex <= 0 || (typeIndex + 1 >= calendarId.length())) {
 			return null;
@@ -241,13 +251,10 @@ public class UserCalendarWebService {
 			CalSecurityCallback secCallback = CalSecurityCallbackFactory.createCourseCalendarCallback(userCourseEnv);
 			wrapper = CourseCalendars.getCourseCalendarWrapper(ureq, userCourseEnv, secCallback);
 		} else if("user".equals(type) && calendarModule.isEnablePersonalCalendar()) {
-			if(id.equals(ureq.getIdentity().getName())) {
-				wrapper = getPersonalCalendar(ureq.getIdentity());
+			if(id.equals(identity.getName()) || id.equals(identity.getKey().toString())) {
+				wrapper = getPersonalCalendar(identity);
 			} else {
-				Identity identity = securityManager.findIdentityByName(id);
-				if(isManager(identity, ureq.getHttpReq())) {
-					wrapper = getPersonalCalendar(identity);
-				}
+				log.warn("Personal calendar id {} doesn't match identity key: {}", id, identity.getKey());
 			}
 		}
 		return wrapper;
diff --git a/src/main/java/org/olat/restapi/security/AuthenticationWebService.java b/src/main/java/org/olat/restapi/security/AuthenticationWebService.java
index 482c898409c..b47b8d1c881 100644
--- a/src/main/java/org/olat/restapi/security/AuthenticationWebService.java
+++ b/src/main/java/org/olat/restapi/security/AuthenticationWebService.java
@@ -52,6 +52,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
  * Initial Date:  7 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Deprecated
 @Path("auth")
 @Component
 public class AuthenticationWebService {
@@ -110,7 +111,7 @@ public class AuthenticationWebService {
 			"	  not possible.\n" + 
 			"	  \n" + 
 			"	  When using the REST API, best-practice is to use basic authentication and\n" + 
-			"	  activate cookies in your HTTP client for automatic session management.")
+			"	  activate cookies in your HTTP client for automatic session management.", deprecated=true)
 	@ApiResponse(responseCode = "200", description = "Say hello to the authenticated user, and\n" + 
 			"	 *                                  give it a security token\n" + 
 			"	 *                                  &lt;hello&gt;Hello john&lt;/hello&gt;")
diff --git a/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java b/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
index 4ac7781b594..1d64ce8d5cf 100644
--- a/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
+++ b/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
@@ -67,6 +67,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
  * 
  * @author srosse, stephane.rosse@frentix.com
  */
+@Deprecated
 @Tag(name = "Users")
 @Component
 @Path("users/{username}/auth")
@@ -103,7 +104,7 @@ public class UserAuthenticationWebService {
 	 * @return
 	 */
 	@GET
-	@Operation(summary = "Returns all user authentications", description = "Returns all user authentications")
+	@Operation(summary = "Returns all user authentications", description = "Returns all user authentications", deprecated=true)
 	@ApiResponse(responseCode = "200", description = "The list of all users in the OLAT system", content = {
 			@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = AuthenticationVO.class))),
 			@Content(mediaType = "application/xml", array = @ArraySchema(schema = @Schema(implementation = AuthenticationVO.class))) })
@@ -145,7 +146,7 @@ public class UserAuthenticationWebService {
 	 * @return the saved authentication
 	 */
 	@PUT
-	@Operation(summary = "Creates and persists an authentication", description = "Creates and persists an authentication")
+	@Operation(summary = "Creates and persists an authentication", description = "Creates and persists an authentication", deprecated=true)
 	@ApiResponse(responseCode = "200", description = "The saved authentication", content = {
 			@Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationVO.class)),
 			@Content(mediaType = "application/xml", schema = @Schema(implementation = AuthenticationVO.class)) })
@@ -196,7 +197,7 @@ public class UserAuthenticationWebService {
 	 */
 	@DELETE
 	@Path("{authKey}")
-	@Operation(summary = "Deletes an authentication from the system", description = "Deletes an authentication from the system")
+	@Operation(summary = "Deletes an authentication from the system", description = "Deletes an authentication from the system", deprecated=true)
 	@ApiResponse(responseCode = "200", description = "The authentication successfully deleted")
 	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
 	@ApiResponse(responseCode = "404", description = "The identity not found")
@@ -229,7 +230,7 @@ public class UserAuthenticationWebService {
 	 */
 	@POST
 	@Path("password")
-	@Operation(summary = "Change the password of a user", description = "Change the password of a user")
+	@Operation(summary = "Change the password of a user", description = "Change the password of a user", deprecated=true)
 	@ApiResponse(responseCode = "200", description = "The password successfully changed")
 	@ApiResponse(responseCode = "304", description = "The password was not changed")
 	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
diff --git a/src/main/java/org/olat/user/restapi/UserAuthenticationsWebService.java b/src/main/java/org/olat/user/restapi/UserAuthenticationsWebService.java
new file mode 100644
index 00000000000..554ac90a523
--- /dev/null
+++ b/src/main/java/org/olat/user/restapi/UserAuthenticationsWebService.java
@@ -0,0 +1,254 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.user.restapi;
+
+import static org.olat.restapi.security.RestSecurityHelper.getIdentity;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.logging.log4j.Logger;
+import org.olat.basesecurity.Authentication;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.core.id.Identity;
+import org.olat.core.id.Roles;
+import org.olat.core.logging.Tracing;
+import org.olat.login.auth.OLATAuthManager;
+import org.olat.restapi.security.RestSecurityHelper;
+import org.olat.restapi.support.ObjectFactory;
+import org.olat.restapi.support.vo.AuthenticationVO;
+import org.olat.restapi.support.vo.ErrorVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * 
+ * Initial date: 10 août 2020<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Tag(name = "Users")
+@Component
+@Path("users/{identityKey}/authentications")
+public class UserAuthenticationsWebService {
+	
+	private static final Logger log = Tracing.createLoggerFor(UserAuthenticationsWebService.class);
+	
+	private static final String VERSION = "2.0";
+	
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
+	private OLATAuthManager authManager;
+	
+	/**
+	 * The version of the User Authentication Web Service
+	 * 
+	 * @return The version number
+	 */
+	@GET
+	@Path("version")
+	@Operation(summary = "The version of the User Authentication Web Service", description = "The version of the User Authentication Web Service")
+	@ApiResponse(responseCode = "200", description = "The version of this specific Web Service")
+	@Produces(MediaType.TEXT_PLAIN)
+	public Response getVersion() {
+		return Response.ok(VERSION).build();
+	}
+
+	/**
+	 * Returns all user authentications
+	 * 
+	 * @param identityKey The identity primary key of the user to retrieve the list authentication
+	 * @param request The HTTP request
+	 * @return A list of authentication
+	 */
+	@GET
+	@Operation(summary = "Returns all user authentications", description = "Returns all user authentications")
+	@ApiResponse(responseCode = "200", description = "The list of all users in the OLAT system", content = {
+			@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = AuthenticationVO.class))),
+			@Content(mediaType = "application/xml", array = @ArraySchema(schema = @Schema(implementation = AuthenticationVO.class))) })
+	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
+	@ApiResponse(responseCode = "404", description = "The identity not found")
+	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+	public Response getAuthenticationTokenList(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
+		Identity identity = securityManager.loadIdentityByKey(identityKey);
+		if(identityKey == null) {
+			return Response.serverError().status(Status.NOT_FOUND).build();
+		}
+		if(!isManager(identity, request)) {
+			return Response.serverError().status(Status.FORBIDDEN).build();
+		}
+		
+		List<Authentication> authentications = securityManager.getAuthentications(identity);
+		AuthenticationVO[] vos = new AuthenticationVO[authentications.size()];
+		int count = 0;
+		for(Authentication authentication:authentications) {
+			vos[count++] = ObjectFactory.get(authentication, false);
+		}
+		return Response.ok(vos).build();
+	}
+	
+	/**
+	 * Creates and persists an authentication
+	 *
+	 * @param identityKey The identity key of the user
+	 * @param authenticationVO The authentication object to persist
+	 * @param request The HTTP request
+	 * @return the saved authentication
+	 */
+	@PUT
+	@Operation(summary = "Creates and persists an authentication", description = "Creates and persists an authentication")
+	@ApiResponse(responseCode = "200", description = "The saved authentication", content = {
+			@Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationVO.class)),
+			@Content(mediaType = "application/xml", schema = @Schema(implementation = AuthenticationVO.class)) })
+	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
+	@ApiResponse(responseCode = "404", description = "The identity not found") 
+	@ApiResponse(responseCode = "406", description = "Cannot create the authentication for an unkown reason")
+	@ApiResponse(responseCode = "409", description = "Cannot create the authentication because the authentication username is already used by someone else within the same provider")	
+	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+	public Response create(@PathParam("identityKey") Long identityKey, AuthenticationVO authenticationVO, @Context HttpServletRequest request) {
+		Identity identity = securityManager.loadIdentityByKey(authenticationVO.getIdentityKey(), false);
+		if(identity == null) {
+			return Response.serverError().status(Status.NOT_FOUND).build();
+		}
+		if(!isManager(identity, request)) {
+			return Response.serverError().status(Status.FORBIDDEN).build();
+		}
+		
+		String provider = authenticationVO.getProvider();
+		String authUsername = authenticationVO.getAuthUsername();
+		String credentials = authenticationVO.getCredential();
+		
+		Authentication currentAuthentication = securityManager.findAuthenticationByAuthusername(authUsername, provider);
+		if(currentAuthentication != null && !currentAuthentication.getIdentity().equals(identity)) {
+			ErrorVO error = new ErrorVO();
+			error.setCode("unkown:409");
+			error.setTranslation("Authentication name used by: " + currentAuthentication.getIdentity().getUser().getEmail());
+			return Response.serverError().status(Status.CONFLICT).entity(error).build();
+		}
+		
+		Authentication authentication = securityManager.createAndPersistAuthentication(identity, provider, authUsername, credentials, null);
+		if(authentication == null) {
+			return Response.serverError().status(Status.NOT_ACCEPTABLE).build();
+		}
+		log.info(Tracing.M_AUDIT, "New authentication created for {} with provider {}", authUsername, provider);
+		AuthenticationVO savedAuth = ObjectFactory.get(authentication, true);
+		return Response.ok(savedAuth).build();
+	}
+
+	/**
+	 * Deletes an authentication from the system
+	 * 
+	 * @param identityKey The identity key of the user
+	 * @param authKey The authentication key identifier
+	 * @param request The HTTP request
+	 * @return <code>Response</code> object. The operation status (success or
+	 *         fail)
+	 */
+	@DELETE
+	@Path("{authKey}")
+	@Operation(summary = "Deletes an authentication from the system", description = "Deletes an authentication from the system")
+	@ApiResponse(responseCode = "200", description = "The authentication successfully deleted")
+	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
+	@ApiResponse(responseCode = "404", description = "The identity not found")
+	public Response delete(@PathParam("identityKey") Long identityKey, @PathParam("authKey") Long authKey, @Context HttpServletRequest request) {
+		Identity identity = securityManager.loadIdentityByKey(identityKey);
+		if(identity == null) {
+			return Response.serverError().status(Status.NOT_FOUND).build();
+		}
+		if(!isManager(identity, request)) {
+			return Response.serverError().status(Status.FORBIDDEN).build();
+		}
+		
+		List<Authentication> authentications = securityManager.getAuthentications(identity);
+		for(Authentication authentication:authentications) {
+			if(authKey.equals(authentication.getKey())) {
+				securityManager.deleteAuthentication(authentication);
+				return Response.ok().build();
+			}
+		}
+		return Response.serverError().status(Status.NOT_FOUND).build();
+	}
+	
+	/**
+	 * Change the password of a user.
+	 * 
+	 * @param username The identity key of the user to change the password
+	 * @param newPassword The new password
+	 * @param request The HTTP request
+	 * @return <code>Response</code> object. The operation status (success or fail)
+	 */
+	@POST
+	@Path("password")
+	@Operation(summary = "Change the password of a user", description = "Change the password of a user")
+	@ApiResponse(responseCode = "200", description = "The password successfully changed")
+	@ApiResponse(responseCode = "304", description = "The password was not changed")
+	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
+	@ApiResponse(responseCode = "404", description = "The identity or the authentication not found")
+	public Response changePassword(@PathParam("identityKey") Long identityKey, @FormParam("newPassword") String newPassword,
+			@Context HttpServletRequest request) {
+		Identity doer = getIdentity(request);
+		if(doer == null) {
+			return Response.serverError().status(Status.FORBIDDEN).build();
+		}
+		Identity identity = securityManager.loadIdentityByKey(identityKey);
+		if(identity == null) {
+			return Response.serverError().status(Status.NOT_FOUND).build();
+		}
+		if(!isManager(identity, request)) {
+			return Response.serverError().status(Status.FORBIDDEN).build();
+		}
+		
+		boolean ok = authManager.changePassword(doer, identity, newPassword);
+		return (ok ? Response.ok() : Response.notModified()).build();
+	}
+	
+	private boolean isManager(Identity identity, HttpServletRequest request) {
+		Roles managerRoles = RestSecurityHelper.getRoles(request);
+		Roles identityRoles = securityManager.getRoles(identity);
+		return managerRoles.isManagerOf(OrganisationRoles.usermanager, identityRoles)
+				|| managerRoles.isManagerOf(OrganisationRoles.rolesmanager, identityRoles)
+				|| managerRoles.isManagerOf(OrganisationRoles.administrator, identityRoles);
+		
+	}
+}
diff --git a/src/test/java/org/olat/restapi/UserAuthenticationMgmtTest.java b/src/test/java/org/olat/restapi/UserAuthenticationMgmtTest.java
index 5296de5ce46..f2ab3bae3cc 100644
--- a/src/test/java/org/olat/restapi/UserAuthenticationMgmtTest.java
+++ b/src/test/java/org/olat/restapi/UserAuthenticationMgmtTest.java
@@ -50,13 +50,13 @@ import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
+import org.apache.logging.log4j.Logger;
 import org.junit.Assert;
 import org.junit.Test;
 import org.olat.basesecurity.Authentication;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Encoder;
 import org.olat.login.auth.OLATAuthManager;
@@ -78,6 +78,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
  * Initial Date:  15 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Deprecated
 public class UserAuthenticationMgmtTest extends OlatRestTestCase {
 	
 	private static final Logger log = Tracing.createLoggerFor(UserAuthenticationMgmtTest.class);
diff --git a/src/test/java/org/olat/restapi/UserAuthenticationsWebServiceTest.java b/src/test/java/org/olat/restapi/UserAuthenticationsWebServiceTest.java
new file mode 100644
index 00000000000..58aaa694a0f
--- /dev/null
+++ b/src/test/java/org/olat/restapi/UserAuthenticationsWebServiceTest.java
@@ -0,0 +1,256 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.restapi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+import org.olat.basesecurity.Authentication;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.Encoder;
+import org.olat.login.auth.OLATAuthManager;
+import org.olat.restapi.support.vo.AuthenticationVO;
+import org.olat.restapi.support.vo.ErrorVO;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatRestTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * 
+ * Initial date: 10 août 2020<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class UserAuthenticationsWebServiceTest extends OlatRestTestCase {
+	
+	private static final Logger log = Tracing.createLoggerFor(UserAuthenticationsWebServiceTest.class);
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
+	private OLATAuthManager authManager;
+	
+	
+	@Test
+	public void getAuthentications() throws IOException, URISyntaxException {
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login("administrator", "openolat"));
+		Identity administrator = securityManager.findIdentityByLogin("administrator");
+		
+		URI request = UriBuilder.fromUri(getContextURI())
+				.path("users").path(administrator.getKey().toString()).path("authentications")
+				.build();
+		HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+		List<AuthenticationVO> vos = parseAuthenticationArray(response.getEntity());
+		Assert.assertNotNull(vos);
+		Assert.assertFalse(vos.isEmpty());
+
+		conn.shutdown();
+	}
+	
+	@Test
+	public void createAuthentications() throws IOException, URISyntaxException {
+		RestConnection conn = new RestConnection();
+		Identity adminIdent = JunitTestHelper.findIdentityByLogin("administrator");
+		try {
+			Authentication refAuth = securityManager.findAuthentication(adminIdent, "REST-API");
+			if(refAuth != null) {
+				securityManager.deleteAuthentication(refAuth);
+			}
+		} catch(Exception e) {
+			//
+		}
+		dbInstance.commitAndCloseSession();
+		
+		assertTrue(conn.login("administrator", "openolat"));
+
+		AuthenticationVO vo = new AuthenticationVO();
+		vo.setAuthUsername("administrator");
+		vo.setIdentityKey(adminIdent.getKey());
+		vo.setProvider("REST-API");
+		vo.setCredential("credentials");
+		
+		URI request = UriBuilder.fromUri(getContextURI())
+				.path("users").path(adminIdent.getKey().toString()).path("authentications")
+				.build();
+		HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true);
+		conn.addJsonEntity(method, vo);
+
+		HttpResponse response = conn.execute(method);
+		Assert.assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201);
+		AuthenticationVO savedAuth = conn.parse(response, AuthenticationVO.class);
+		Authentication refAuth = securityManager.findAuthentication(adminIdent, "REST-API");
+
+		Assert.assertNotNull(refAuth);
+		Assert.assertNotNull(refAuth.getKey());
+		Assert.assertTrue(refAuth.getKey().longValue() > 0);
+		Assert.assertNotNull(savedAuth);
+		Assert.assertNotNull(savedAuth.getKey());
+		assertTrue(savedAuth.getKey().longValue() > 0);
+		assertEquals(refAuth.getKey(), savedAuth.getKey());
+		assertEquals(refAuth.getAuthusername(), savedAuth.getAuthUsername());
+		assertEquals(refAuth.getIdentity().getKey(), savedAuth.getIdentityKey());
+		assertEquals(refAuth.getProvider(), savedAuth.getProvider());
+		assertEquals(refAuth.getCredential(), savedAuth.getCredential());
+		
+		conn.shutdown();
+	}
+	
+	/**
+	 * Check if the REST call return a specific error if the pair authentication user name and provider
+	 * is already used.
+	 * 
+	 */
+	@Test
+	public void createAuthentications_checkDuplicate() throws IOException, URISyntaxException {
+		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("check-auth-1");
+		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("check-auth-2");
+		String authUsername = UUID.randomUUID().toString();
+		dbInstance.commitAndCloseSession();
+		
+		RestConnection conn = new RestConnection();
+		Assert.assertTrue(conn.login("administrator", "openolat"));
+
+		//set the first authentication
+		AuthenticationVO vo1 = new AuthenticationVO();
+		vo1.setAuthUsername(authUsername);
+		vo1.setIdentityKey(id1.getKey());
+		vo1.setProvider("REST-API");
+		vo1.setCredential("credentials");
+		URI request1 = UriBuilder.fromUri(getContextURI()).path("users").path(id1.getKey().toString()).path("authentications").build();
+		HttpPut method1 = conn.createPut(request1, MediaType.APPLICATION_JSON, true);
+		conn.addJsonEntity(method1, vo1);
+
+		HttpResponse response1 = conn.execute(method1);
+		Assert.assertEquals(200, response1.getStatusLine().getStatusCode());
+		conn.parse(response1, AuthenticationVO.class);
+		Authentication refAuth1 = securityManager.findAuthentication(id1, "REST-API");
+		Assert.assertNotNull(refAuth1);
+		Assert.assertEquals(id1, refAuth1.getIdentity());
+
+		// set the second which duplicates the first
+		AuthenticationVO vo2 = new AuthenticationVO();
+		vo2.setAuthUsername(authUsername);
+		vo2.setIdentityKey(id2.getKey());
+		vo2.setProvider("REST-API");
+		vo2.setCredential("credentials");
+		URI request2 = UriBuilder.fromUri(getContextURI()).path("users").path(id2.getKey().toString()).path("authentications").build();
+		HttpPut method2 = conn.createPut(request2, MediaType.APPLICATION_JSON, true);
+		conn.addJsonEntity(method2, vo2);
+
+		HttpResponse response2 = conn.execute(method2);
+		Assert.assertEquals(409, response2.getStatusLine().getStatusCode());
+		ErrorVO error = conn.parse(response2, ErrorVO.class);
+		Assert.assertNotNull(error);
+
+		conn.shutdown();
+	}
+	
+	@Test
+	public void deleteAuthentications() throws IOException, URISyntaxException {
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login("administrator", "openolat"));
+		
+		//create an authentication token
+		Identity adminIdent = JunitTestHelper.findIdentityByLogin("administrator");
+		Authentication authentication = securityManager.createAndPersistAuthentication(adminIdent, "REST-A-2", "administrator", "credentials", Encoder.Algorithm.sha512);
+		assertTrue(authentication != null && authentication.getKey() != null && authentication.getKey().longValue() > 0);
+		dbInstance.intermediateCommit();
+		
+		//delete an authentication token
+		URI request = UriBuilder.fromUri(getContextURI()).path("users").path(adminIdent.getKey().toString())
+				.path("authentications").path(authentication.getKey().toString()).build();
+		HttpDelete method = conn.createDelete(request, MediaType.APPLICATION_XML);
+		HttpResponse response = conn.execute(method);
+		assertEquals(200, response.getStatusLine().getStatusCode());
+		EntityUtils.consume(response.getEntity());
+		
+		Authentication refAuth = securityManager.findAuthentication(adminIdent, "REST-A-2");
+		assertNull(refAuth);
+		
+		conn.shutdown();
+	}
+	
+	@Test
+	public void changePassword() throws IOException, URISyntaxException {
+		Identity user = JunitTestHelper.createAndPersistIdentityAsRndUser("rest-chg-pwd");
+		dbInstance.commitAndCloseSession();
+		
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login("administrator", "openolat"));
+
+		URI request = UriBuilder.fromUri(getContextURI())
+				.path("users").path(user.getKey().toString()).path("authentications").path("password")
+				.build();
+		HttpPost method = conn.createPost(request, "*/*");
+		conn.addEntity(method, new BasicNameValuePair("newPassword", "top-secret"));
+		HttpResponse response = conn.execute(method);
+		Assert.assertNotNull(response);
+		Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+		EntityUtils.consume(response.getEntity());
+		
+		//check
+		Identity reloadedUser = authManager.authenticate(user, user.getName(), "top-secret");
+		Assert.assertNotNull(reloadedUser);
+		Assert.assertEquals(user, reloadedUser);
+	}
+	
+	private List<AuthenticationVO> parseAuthenticationArray(HttpEntity entity) {
+		try(InputStream in=entity.getContent()) {
+			ObjectMapper mapper = new ObjectMapper(jsonFactory); 
+			return mapper.readValue(in, new TypeReference<List<AuthenticationVO>>(){/* */});
+		} catch (Exception e) {
+			log.error("Cannot parse an array of AuthenticationVO", e);
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 2bdc53914a6..0dfadfd2edc 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -450,6 +450,7 @@ import org.junit.runners.Suite;
 	org.olat.restapi.RemindersWebServiceTest.class,
 	org.olat.restapi.RestApiLoginFilterTest.class,
 	org.olat.restapi.UserAuthenticationMgmtTest.class,
+	org.olat.restapi.UserAuthenticationsWebServiceTest.class,
 	org.olat.restapi.UserFoldersTest.class,
 	org.olat.restapi.UserCoursesTest.class,
 	org.olat.restapi.UserMgmtTest.class,
-- 
GitLab