From f17431b61ed19e6dbe1856a8837abe650a339a61 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 25 Mar 2020 09:28:26 +0100
Subject: [PATCH] OO-4584: limit templates by roles

---
 .../course/nodes/BigBlueButtonCourseNode.java |  3 -
 .../bigbluebutton/BigBlueButtonRoles.java     | 64 ++++++++++++++++++-
 .../manager/BigBlueButtonManagerImpl.java     |  2 +
 .../BigBlueButtonMeetingTemplateImpl.java     |  4 +-
 .../BigBlueButtonEditMeetingsController.java  | 49 +++++++++++++-
 .../EditBigBlueButtonMeetingController.java   | 28 ++++++--
 .../EditBigBlueButtonTemplateController.java  | 33 +++++++++-
 .../ui/_i18n/LocalStrings_de.properties       |  5 ++
 .../ui/_i18n/LocalStrings_en.properties       |  5 ++
 9 files changed, 177 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/olat/course/nodes/BigBlueButtonCourseNode.java b/src/main/java/org/olat/course/nodes/BigBlueButtonCourseNode.java
index 8a2cc327697..c0056ddb349 100644
--- a/src/main/java/org/olat/course/nodes/BigBlueButtonCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/BigBlueButtonCourseNode.java
@@ -21,7 +21,6 @@ package org.olat.course.nodes;
 
 import java.util.List;
 
-import org.apache.logging.log4j.Logger;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.control.Controller;
@@ -30,7 +29,6 @@ import org.olat.core.gui.control.generic.messages.MessageUIFactory;
 import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Roles;
-import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
 import org.olat.course.ICourse;
 import org.olat.course.condition.ConditionEditController;
@@ -57,7 +55,6 @@ import org.olat.repository.RepositoryEntry;
 public class BigBlueButtonCourseNode extends AbstractAccessableCourseNode {
 	
 	private static final long serialVersionUID = 7965344505304490859L;
-	private static final Logger log = Tracing.createLoggerFor(BigBlueButtonCourseNode.class);
 	private static final String TYPE = "bigbluebutton";
 
 	// configuration
diff --git a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonRoles.java b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonRoles.java
index 53c3192410b..b161539fc50 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonRoles.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonRoles.java
@@ -19,6 +19,13 @@
  */
 package org.olat.modules.bigbluebutton;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.olat.core.util.StringHelper;
+
+import edu.emory.mathcs.backport.java.util.Collections;
+
 /**
  * 
  * Initial date: 24 mars 2020<br>
@@ -30,6 +37,59 @@ public enum BigBlueButtonRoles {
 	coach,
 	owner,
 	author,
-	administrator
-
+	administrator;
+	
+	public boolean accept(BigBlueButtonRoles role) {
+		if(role == null) return false;
+		if(this == role) {
+			return true;
+		}
+		if(role == administrator) {
+			return true;
+		}
+		if(role == author) {
+			return (this == author || this == owner || this == coach);
+		}
+		return false;
+	}
+	
+	public static List<BigBlueButtonRoles> valuesAsList() {
+		List<BigBlueButtonRoles> roles = new ArrayList<>();
+		Collections.addAll(roles, BigBlueButtonRoles.values());
+		return roles;
+	}
+	
+	public static List<BigBlueButtonRoles> toList(String val) {
+		List<BigBlueButtonRoles> roles = new ArrayList<>();
+		if(StringHelper.containsNonWhitespace(val)) {
+			String[] valArray = val.split("[,]");
+			if(valArray != null && valArray.length > 0) {
+				for(String v:valArray) {
+					BigBlueButtonRoles role = BigBlueButtonRoles.valueOfSecure(v);
+					if(role != null) {
+						roles.add(role);
+					}
+				}
+			}	
+		}
+		return roles;
+	}
+	
+	public static BigBlueButtonRoles valueOfSecure(String val) {
+		for(BigBlueButtonRoles role:BigBlueButtonRoles.values()) {
+			if(role.name().equals(val)) {
+				return role;
+			}
+		}
+		return null;
+	}
+	
+	public static String toString(List<BigBlueButtonRoles> roles) {
+		StringBuilder sb = new StringBuilder();
+		for(BigBlueButtonRoles role:roles) {
+			if(sb.length() > 0) sb.append(",");
+			sb.append(role.name());
+		}
+		return sb.toString();
+	}
 }
diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
index 1a40c108ea8..5e21ba35451 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
@@ -49,6 +49,7 @@ import org.olat.modules.bigbluebutton.BigBlueButtonMeeting;
 import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate;
 import org.olat.modules.bigbluebutton.BigBlueButtonModule;
 import org.olat.modules.bigbluebutton.BigBlueButtonRecording;
+import org.olat.modules.bigbluebutton.BigBlueButtonRoles;
 import org.olat.modules.bigbluebutton.GuestPolicyEnum;
 import org.olat.modules.bigbluebutton.model.BigBlueButtonError;
 import org.olat.modules.bigbluebutton.model.BigBlueButtonErrorCodes;
@@ -137,6 +138,7 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 		template.setMaxConcurrentMeetings(maxConcurrentMeetings);
 		template.setMaxParticipants(maxParticipants);
 		template.setMaxDuration(maxDuration);
+		template.setPermittedRolesEnum(BigBlueButtonRoles.valuesAsList());
 		template.setMuteOnStart(muteOnStart);
 		template.setAutoStartRecording(autoStartRecording);
 		template.setAllowStartStopRecording(allowStartStopRecording);
diff --git a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingTemplateImpl.java b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingTemplateImpl.java
index 328155bd453..14e9816315e 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingTemplateImpl.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingTemplateImpl.java
@@ -387,7 +387,7 @@ public class BigBlueButtonMeetingTemplateImpl implements Persistable, BigBlueBut
 
 	@Override
 	public List<BigBlueButtonRoles> getPermittedRolesEnum() {
-		return null;
+		return BigBlueButtonRoles.toList(permittedRoles);
 	}
 
 	@Override
@@ -395,7 +395,7 @@ public class BigBlueButtonMeetingTemplateImpl implements Persistable, BigBlueBut
 		if(roles == null || roles.isEmpty()) {
 			setPermittedRoles(null);
 		} else {
-			
+			setPermittedRoles(BigBlueButtonRoles.toString(roles));
 		}
 	}
 
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
index ffaf19c6c2f..84834a12e79 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.bigbluebutton.ui;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.olat.core.commons.persistence.SortKey;
@@ -41,14 +42,19 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
 import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
+import org.olat.core.id.Roles;
 import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupService;
 import org.olat.modules.bigbluebutton.BigBlueButtonManager;
 import org.olat.modules.bigbluebutton.BigBlueButtonMeeting;
 import org.olat.modules.bigbluebutton.BigBlueButtonModule;
+import org.olat.modules.bigbluebutton.BigBlueButtonRoles;
 import org.olat.modules.bigbluebutton.model.BigBlueButtonErrors;
 import org.olat.modules.bigbluebutton.ui.BigBlueButtonMeetingTableModel.BMeetingsCols;
 import org.olat.modules.gotomeeting.ui.GoToMeetingTableModel.MeetingsCols;
 import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.model.RepositoryEntrySecurity;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -72,10 +78,14 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 	private final RepositoryEntry entry;
 	private final BusinessGroup businessGroup;
 
+	@Autowired
+	private RepositoryManager repositoryManager;
 	@Autowired
 	private BigBlueButtonModule bigBlueButtonModule;
 	@Autowired
 	private BigBlueButtonManager bigBlueButtonManager;
+	@Autowired
+	private BusinessGroupService businessGroupService;
 	
 	public BigBlueButtonEditMeetingsController(UserRequest ureq, WindowControl wControl,
 			RepositoryEntry entry, String subIdentifier, BusinessGroup group, boolean readOnly) {
@@ -183,8 +193,10 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 
 	private void doAddMeeting(UserRequest ureq) {
 		if(guardModalController(editMeetingCtlr)) return;
-		
-		editMeetingCtlr = new EditBigBlueButtonMeetingController(ureq, getWindowControl(), entry, subIdent, businessGroup);
+
+		List<BigBlueButtonRoles> editionRoles= getPermittedRoles(ureq);
+		editMeetingCtlr = new EditBigBlueButtonMeetingController(ureq, getWindowControl(),
+				entry, subIdent, businessGroup, editionRoles);
 		listenTo(editMeetingCtlr);
 		
 		cmc = new CloseableModalController(getWindowControl(), "close", editMeetingCtlr.getInitialComponent(),
@@ -196,7 +208,9 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 	private void doEditMeeting(UserRequest ureq, BigBlueButtonMeeting meeting) {
 		if(guardModalController(editMeetingCtlr)) return;
 		
-		editMeetingCtlr = new EditBigBlueButtonMeetingController(ureq, getWindowControl(), meeting);
+		List<BigBlueButtonRoles> editionRoles= getPermittedRoles(ureq);
+		editMeetingCtlr = new EditBigBlueButtonMeetingController(ureq, getWindowControl(),
+				meeting, editionRoles);
 		listenTo(editMeetingCtlr);
 		
 		cmc = new CloseableModalController(getWindowControl(), "close", editMeetingCtlr.getInitialComponent(),
@@ -205,6 +219,35 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 		listenTo(cmc);
 	}
 	
+	private List<BigBlueButtonRoles> getPermittedRoles(UserRequest ureq) {
+		Roles roles = ureq.getUserSession().getRoles();
+		
+		List<BigBlueButtonRoles> editionRoles = new ArrayList<>();
+		if(businessGroup != null) {
+			if(roles.isAdministrator()) {
+				editionRoles.add(BigBlueButtonRoles.administrator);
+			}
+			if(businessGroupService.isIdentityInBusinessGroup(getIdentity(), businessGroup.getKey(), true, false, null)) {
+				editionRoles.add(BigBlueButtonRoles.coach);
+			}
+		} else if(entry != null) {
+			RepositoryEntrySecurity reSecurity = repositoryManager.isAllowed(getIdentity(), roles, entry);
+			if(roles.isAdministrator()) {
+				editionRoles.add(BigBlueButtonRoles.administrator);
+			}
+			if(reSecurity.isAuthor()) {
+				editionRoles.add(BigBlueButtonRoles.author);
+			}
+			if(reSecurity.isEntryAdmin()) {
+				editionRoles.add(BigBlueButtonRoles.owner);
+			}
+			if(reSecurity.isCourseCoach()) {
+				editionRoles.add(BigBlueButtonRoles.coach);
+			}
+		}
+		return editionRoles;
+	}
+	
 	private void doConfirmDelete(UserRequest ureq, BigBlueButtonMeeting meeting) {
 		String confirmDeleteTitle = translate("confirm.delete.meeting.title", new String[]{ meeting.getName() });
 		String confirmDeleteText = translate("confirm.delete.meeting", new String[]{ meeting.getName() });
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java
index 5d190b387a2..bace9acb687 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java
@@ -44,6 +44,7 @@ import org.olat.modules.bigbluebutton.BigBlueButtonManager;
 import org.olat.modules.bigbluebutton.BigBlueButtonMeeting;
 import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate;
 import org.olat.modules.bigbluebutton.BigBlueButtonModule;
+import org.olat.modules.bigbluebutton.BigBlueButtonRoles;
 import org.olat.repository.RepositoryEntry;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -71,6 +72,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 	private final RepositoryEntry entry;
 	private final BusinessGroup businessGroup;
 	private BigBlueButtonMeeting meeting;
+	private final List<BigBlueButtonRoles> editionRoles;
 	private List<BigBlueButtonMeetingTemplate> templates;
 	
 	private FormLink openCalLink;
@@ -83,23 +85,26 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 	private BigBlueButtonManager bigBlueButtonManager;
 	
 	public EditBigBlueButtonMeetingController(UserRequest ureq, WindowControl wControl,
-			RepositoryEntry entry, String subIdent, BusinessGroup businessGroup) {
+			RepositoryEntry entry, String subIdent, BusinessGroup businessGroup, List<BigBlueButtonRoles> editionRoles) {
 		super(ureq, wControl);
 		this.entry = entry;
 		this.subIdent = subIdent;
 		this.businessGroup = businessGroup;
+		this.editionRoles = editionRoles;
 		templates = bigBlueButtonManager.getTemplates();
 		
 		initForm(ureq);
 		updateUI();
 	}
 	
-	public EditBigBlueButtonMeetingController(UserRequest ureq, WindowControl wControl, BigBlueButtonMeeting meeting) {
+	public EditBigBlueButtonMeetingController(UserRequest ureq, WindowControl wControl,
+			BigBlueButtonMeeting meeting, List<BigBlueButtonRoles> editionRoles) {
 		super(ureq, wControl);
 		entry = meeting.getEntry();
 		subIdent = meeting.getSubIdent();
 		businessGroup = meeting.getBusinessGroup();
 		this.meeting = meeting;
+		this.editionRoles = editionRoles;
 		templates = bigBlueButtonManager.getTemplates();
 		
 		initForm(ureq);
@@ -125,7 +130,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 				? null : meeting.getTemplate().getKey();
 		KeyValues templatesKeyValues = new KeyValues();
 		for(BigBlueButtonMeetingTemplate template:templates) {
-			if(template.isEnabled() || template.getKey().equals(selectedTemplateKey)) {
+			if(accept(template) || template.getKey().equals(selectedTemplateKey)) {
 				templatesKeyValues.add(KeyValues.entry(template.getKey().toString(), template.getName()));
 			}
 		}
@@ -145,7 +150,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 				}
 			}
 		}
-		if(!templateSelected) {
+		if(!templateSelected && templatesKeys.length > 0) {
 			templateEl.select(templatesKeys[0], true);
 		}
 		openCalLink = uifactory.addFormLink("calendar.open", formLayout);
@@ -169,7 +174,6 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 		String leadtime = meeting == null ? null : Long.toString(meeting.getLeadTime());
 		leadTimeEl = uifactory.addTextElement("meeting.leadTime", 8, leadtime, formLayout);
 		
-		
 		Date endDate = meeting == null ? null : meeting.getEndDate();
 		endDateEl = uifactory.addDateChooser("meeting.end", "meeting.end", endDate, formLayout);
 		endDateEl.setMandatory(!permanent);
@@ -185,6 +189,20 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 		uifactory.addFormSubmitButton("save", buttonLayout);
 	}
 	
+	private boolean accept(BigBlueButtonMeetingTemplate template) {
+		if(!template.isEnabled()) return false;
+		
+		List<BigBlueButtonRoles> roles = template.getPermittedRolesEnum();
+		for(BigBlueButtonRoles role:roles) {
+			for(BigBlueButtonRoles editionRole:editionRoles) {
+				if(role.accept(editionRole)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
 	private void updateUI() {
 		boolean permanent = permanentEl.isAtLeastSelected(1);
 		startDateEl.setVisible(!permanent);
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonTemplateController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonTemplateController.java
index 90bc2fb3e92..802ffbf2a3b 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonTemplateController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonTemplateController.java
@@ -19,6 +19,9 @@
  */
 package org.olat.modules.bigbluebutton.ui;
 
+import java.util.List;
+import java.util.stream.Collectors;
+
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
@@ -29,12 +32,14 @@ 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.util.KeyValues;
 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.util.StringHelper;
 import org.olat.modules.bigbluebutton.BigBlueButtonManager;
 import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate;
+import org.olat.modules.bigbluebutton.BigBlueButtonRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -52,6 +57,7 @@ public class EditBigBlueButtonTemplateController extends FormBasicController {
 	private TextElement descriptionEl;
 	
 	private MultipleSelectionElement enableEl;
+	private MultipleSelectionElement rolesEl;
 	
 	private TextElement maxConcurrentMeetingsEl;
 	private TextElement maxParticipantsEl;
@@ -115,6 +121,22 @@ public class EditBigBlueButtonTemplateController extends FormBasicController {
 		enableEl = uifactory.addCheckboxesHorizontal("template.enabled", "template.enabled", formLayout, onKeys, new String[] { "" });
 		enableEl.select(onKeys[0], enable);
 		
+		KeyValues rolesKeyValues = new KeyValues();
+		for(BigBlueButtonRoles role:BigBlueButtonRoles.values()) {
+			rolesKeyValues.add(KeyValues.entry(role.name(), translate("role.".concat(role.name()))));
+		}
+		rolesEl = uifactory.addCheckboxesVertical("template.roles", "template.roles", formLayout,
+				rolesKeyValues.keys(), rolesKeyValues.values(), 1);
+		List<BigBlueButtonRoles> roles;
+		if(template != null) {
+			roles = template.getPermittedRolesEnum();
+		} else {
+			roles = BigBlueButtonRoles.valuesAsList();
+		}
+		for(BigBlueButtonRoles role:roles) {
+			rolesEl.select(role.name(), true);
+		}
+		
 		String maxConcurrentMeetings = template == null || template.getMaxConcurrentMeetings() == null ? "" : template.getMaxConcurrentMeetings().toString();
 		maxConcurrentMeetingsEl = uifactory.addTextElement("template.max.concurrent.meetings", "template.max.concurrent.meetings", 8, maxConcurrentMeetings, formLayout);
 		
@@ -122,7 +144,12 @@ public class EditBigBlueButtonTemplateController extends FormBasicController {
 		maxParticipantsEl = uifactory.addTextElement("template.maxParticipants", "template.maxParticipants", 8, maxParticipants, formLayout);
 		maxParticipantsEl.setMandatory(true);
 		
-		String maxDuration = template == null || template.getMaxDuration() == null ? null : template.getMaxDuration().toString();
+		String maxDuration = null;
+		if(template == null) {
+			maxDuration = "240";
+		} else if(template.getMaxDuration() != null) {
+			maxDuration = template.getMaxDuration().toString();
+		}
 		maxDurationEl = uifactory.addTextElement("template.maxDuration", "template.maxDuration", 8, maxDuration, formLayout);
 
 		String[] onValues = new String[] { translate("yes"), translate("no")  };
@@ -310,6 +337,10 @@ public class EditBigBlueButtonTemplateController extends FormBasicController {
 		template.setDescription(descriptionEl.getValue());
 		template.setEnabled(enableEl.isAtLeastSelected(1));
 		
+		List<BigBlueButtonRoles> roles = rolesEl.getSelectedKeys().stream()
+				.map(BigBlueButtonRoles::valueOf).collect(Collectors.toList());
+		template.setPermittedRolesEnum(roles);
+		
 		if(StringHelper.containsNonWhitespace(maxConcurrentMeetingsEl.getValue())
 				&& StringHelper.isLong(maxConcurrentMeetingsEl.getValue())) {
 			template.setMaxConcurrentMeetings(Long.valueOf(maxConcurrentMeetingsEl.getValue()).intValue());
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
index d77f29c756f..7c4725999d2 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
@@ -66,6 +66,10 @@ recordings=Aufzeichnungen
 recording.browser.infos=Aufzeichnungen k\u00F6nnen nur mit Google Chrome und Firefox gesehen werden.
 recording.type.podcast=Podcast
 recording.type.presentation=Vorstellung
+role.administrator=Administrator
+role.author=Autor
+role.coach=Coach
+role.owner=Course owner
 server.overloaded=Es gibt kein Platz verf\u00FCgbar auf dem Server an den gew\u00E4hlten Datum.
 table.header.enabled=Eingeschaltet
 table.header.permanent=Dauernd
@@ -104,6 +108,7 @@ template.max.concurrent.meetings=Max. gleichzeitige Meetings
 template.muteOnStart=Mute on start
 template.name=Name
 template.record=Aufzeichnen
+template.roles=Erlaubt Vorlage zu verwenden
 template.webcamsOnlyForModerator=Webcams only for moderators
 templates.title=Vorlagen
 view=Ansehen
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
index 65544ffa033..1728d68cdd7 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
@@ -66,6 +66,10 @@ recordings=Recordings
 recording.browser.infos=Recordings can only be viewed with Google Chrome or Firefox.
 recording.type.podcast=Podcast
 recording.type.presentation=Presentation
+role.administrator=Administrator
+role.author=Author
+role.coach=coach
+role.owner=Kursbesitzer
 server.overloaded=There is no place available on the server for the choosen dates.
 table.header.enabled=Enabled
 table.header.permanent=Permanent
@@ -104,6 +108,7 @@ template.max.concurrent.meetings=Max. concurrent meetings
 template.muteOnStart=Mute on start
 template.name=Name
 template.record=Record
+template.roles=Allow to use the template
 template.webcamsOnlyForModerator=Webcams only for moderators
 templates.title=Templates
 view=View
-- 
GitLab