diff --git a/config.py.example b/config.py.example
index 30d9180bff8d8894b151621273b2783cce837098..44109dfedce1dfb840521873b7cb647235a32e83 100644
--- a/config.py.example
+++ b/config.py.example
@@ -80,6 +80,7 @@ MAX_INDEX_DAYS = 14
 
 # mail to contact in case of complex errors
 ADMIN_MAIL = "admin@example.com"
+ADMIN_GROUP = "admin"
 
 # accept protocols even with some errors
 # useful for importing old protocols
diff --git a/models/database.py b/models/database.py
index 0788d1ec112b93cf6c3cd0651e9128713e478c8f..1399dadbac158d03918dccd87b5bf52e6fdc8240 100644
--- a/models/database.py
+++ b/models/database.py
@@ -107,6 +107,9 @@ class ProtocolType(db.Model):
     def has_modify_right(self, user):
         return (user is not None and self.modify_group != "" and self.modify_group in user.groups)
 
+    def has_admin_right(self, user):
+        return (user is not None and config.ADMIN_GROUP in user.groups)
+
     @staticmethod
     def get_modifiable_protocoltypes(user):
         return [
diff --git a/server.py b/server.py
index 2bc46061ac05035913242763e66a65de88aad90e..394a10c8c0ff2086a094e20fe192341684ce6520 100755
--- a/server.py
+++ b/server.py
@@ -177,7 +177,8 @@ def new_type():
                 form.private_mail.data, form.public_mail.data,
                 form.use_wiki.data, form.wiki_category.data,
                 form.wiki_only_public.data, form.printer.data,
-                form.calendar.data)
+                form.calendar.data, form.restrict_networks.data,
+                form.allowed_networks.data)
             db.session.add(protocoltype)
             db.session.commit()
             flash("Der Protokolltyp {} wurde angelegt.".format(protocoltype.name), "alert-success")
@@ -224,6 +225,7 @@ def show_type(type_id):
 
 @app.route("/type/delete/<int:type_id>")
 @login_required
+@group_required(config.ADMIN_GROUP)
 def delete_type(type_id):
     user = current_user()
     protocoltype = ProtocolType.query.filter_by(id=type_id).first()
@@ -279,6 +281,7 @@ def edit_reminder(type_id, reminder_id):
 
 @app.route("/type/reminder/delete/<int:type_id>/<int:reminder_id>")
 @login_required
+@group_required(config.ADMIN_GROUP)
 def delete_reminder(type_id, reminder_id):
     protocoltype = ProtocolType.query.filter_by(id=type_id).first()
     if protocoltype is None:
@@ -521,6 +524,7 @@ def show_protocol(protocol_id):
 
 @app.route("/protocol/delete/<int:protocol_id>")
 @login_required
+@group_required(config.ADMIN_GROUP)
 def delete_protocol(protocol_id):
     user = current_user()
     protocol = Protocol.query.filter_by(id=protocol_id).first()
@@ -1016,6 +1020,7 @@ def upload_document(protocol_id):
 
 @app.route("/document/delete/<int:document_id>")
 @login_required
+@group_required(config.ADMIN_GROUP)
 def delete_document(document_id):
     user = current_user()
     document = Document.query.filter_by(id=document_id).first()
@@ -1177,6 +1182,7 @@ def edit_defaultmeta(meta_id):
 
 @app.route("/defaultmeta/delete/<int:meta_id>")
 @login_required
+@group_required(config.ADMIN_GROUP)
 def delete_defaultmeta(meta_id):
     user = current_user()
     meta = DefaultMeta.query.filter_by(id=meta_id).first()
@@ -1186,8 +1192,8 @@ def delete_defaultmeta(meta_id):
     name = meta.name
     type_id = meta.protocoltype.id
     db.session.delete(meta)
-    db.session.delete()
-    flash("Metadatenfeld '{}' gelöscht.", "alert-error")
+    db.session.commit()
+    flash("Metadatenfeld '{}' gelöscht.".format(name), "alert-error")
     return redirect(request.args.get("next") or url_for("show_type", type_id=type_id))
 
 @app.route("/login", methods=["GET", "POST"])
diff --git a/shared.py b/shared.py
index 3900c2da402ddd7b8929c9160c99bd25be29eb9b..f3807bf6b0dd4290126255342252c515c913b200 100644
--- a/shared.py
+++ b/shared.py
@@ -111,15 +111,17 @@ def login_required(function):
             return redirect(url_for("login", next=request.url))
     return decorated_function
 
-def group_required(function, group):
-    @wraps(function)
-    def decorated_function(*args, **kwargs):
-        if group in current_user.groups:
-            return function(*args, **kwargs)
-        else:
-            flash("You do not have the necessary permissions to view this page.")
-            return redirect(request.args.get("next") or url_for("index"))
-    return decorated_function
+def group_required(group):
+    def decorator(function):
+        @wraps(function)
+        def decorated_function(*args, **kwargs):
+            if group in current_user().groups:
+                return function(*args, **kwargs)
+            else:
+                flash("You do not have the necessary permissions to view this page.")
+                return redirect(request.args.get("next") or url_for("index"))
+        return decorated_function
+    return decorator
 
 DATE_KEY = "Datum"
 START_TIME_KEY = "Beginn"
diff --git a/templates/protocol-show.html b/templates/protocol-show.html
index a78aa6d73d9e072523234091b6df191b7df22acb..3ea41a707c23eae6afb0b0760653ea3b265bf5e6 100644
--- a/templates/protocol-show.html
+++ b/templates/protocol-show.html
@@ -8,6 +8,7 @@
 {% set has_public_view_right = protocol.has_public_view_right(user) %}
 {% set has_private_view_right = protocol.has_private_view_right(user) %}
 {% set has_modify_right = protocol.has_modify_right(user) %}
+{% set has_admin_right = protocol.protocoltype.has_admin_right(user) %}
 
 {% block content %}
 <div class="container">
@@ -41,7 +42,9 @@
                 {% if protocol.has_compiled_document() %}
                     <a class="btn btn-success" href="{{url_for("download_document", document_id=protocol.get_compiled_document().id)}}">Download</a>
                 {% endif %}
-                <a class="btn btn-danger" href="{{url_for("delete_protocol", protocol_id=protocol.id)}}" onclick="return confirm('Bist du dir sicher, dass du das Protokoll {{protocol.get_identifier()}} löschen möchtest?');">Löschen</a>
+                {% if has_admin_right %}
+                    <a class="btn btn-danger" href="{{url_for("delete_protocol", protocol_id=protocol.id)}}" onclick="return confirm('Bist du dir sicher, dass du das Protokoll {{protocol.get_identifier()}} löschen möchtest?');">Löschen</a>
+                {% endif %}
             {% endif %}
         </div>
     {% endif %}
diff --git a/views/tables.py b/views/tables.py
index 2922b03f0e051c7cf8b98559caa0753a90e5a97f..c64aa40a18ee12e3d4abb67aec85caf555dc2930 100644
--- a/views/tables.py
+++ b/views/tables.py
@@ -81,7 +81,8 @@ class ProtocolsTable(Table):
         if check_login():
             if user is not None and protocol.protocoltype.has_private_view_right(user):
                 result.append(Table.link(url_for("show_type", type_id=protocol.protocoltype.id), protocol.protocoltype.short_name))
-                result.append(Table.link(url_for("delete_protocol", protocol_id=protocol.id), "Löschen", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?".format(protocol.get_identifier())))
+                if protocol.protocoltype.has_admin_right(user):
+                    result.append(Table.link(url_for("delete_protocol", protocol_id=protocol.id), "Löschen", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?".format(protocol.get_identifier())))
             else:
                 result.extend(["", ""])
         return result
@@ -131,6 +132,7 @@ class ProtocolTypeTable(SingleValueTable):
            + wiki_headers + calendar_headers + network_headers + action_headers)
 
     def row(self):
+        user = current_user()
         general_part = [
             self.value.name,
             self.value.short_name,
@@ -165,6 +167,8 @@ class ProtocolTypeTable(SingleValueTable):
             self.value.allowed_networks
         ]
         action_part = [Table.link(url_for("delete_type", type_id=self.value.id), "Löschen", confirm="Bist du dir sicher, dass du den Protokolltype {} löschen möchtest?".format(self.value.name))]
+        if not self.value.has_admin_right(user):
+            action_part = [""]
         return (general_part + mail_part + printing_part + wiki_part + 
             calendar_part + network_part + action_part)
 
@@ -197,15 +201,19 @@ class MeetingRemindersTable(Table):
         return ["Zeit", "Einladen", "Zusätzlicher Mailinhalt", ""]
 
     def row(self, reminder):
-        return [
+        user = current_user()
+        general_part = [
             "{} Tage".format(reminder.days_before),
             self.get_send_summary(reminder),
-            reminder.additional_text or "",
-            Table.concat([
-                Table.link(url_for("edit_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Ändern"),
-                Table.link(url_for("delete_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Löschen", confirm="Bist du dir sicher, dass du die Einladungsmail {} Tage vor der Sitzung löschen willst?".format(reminder.days_before))
-            ])
+            reminder.additional_text or ""
         ]
+        action_links = [
+            Table.link(url_for("edit_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Ändern"),
+        ]
+        if self.protocoltype.has_admin_right(user):
+            action_links.append(Table.link(url_for("delete_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Löschen", confirm="Bist du dir sicher, dass du die Einladungsmail {} Tage vor der Sitzung löschen willst?".format(reminder.days_before)))
+        action_part = [Table.concat(action_links)]
+        return general_part + action_part
 
     def get_send_summary(self, reminder):
         parts = []
@@ -333,15 +341,15 @@ class DocumentsTable(Table):
 
     def row(self, document):
         user = current_user()
-        links = [Table.link(url_for("delete_document", document_id=document.id), "Löschen", confirm="Bist du dir sicher, dass du das Dokument {} löschen willst?".format(document.name))]
-        if config.PRINTING_ACTIVE:
+        links = []
+        if config.PRINTING_ACTIVE and document.protocol.has_modify_right(user):
             links.append(Table.link(url_for("print_document", document_id=document.id), "Drucken"))
+        if document.protocol.protocoltype.has_admin_right(user):
+            links.append(Table.link(url_for("delete_document", document_id=document.id), "Löschen", confirm="Bist du dir sicher, dass du das Dokument {} löschen willst?".format(document.name)))
         return [
             document.id,
             Table.link(url_for("download_document", document_id=document.id), document.name),
             Table.concat(links)
-                if document.protocol.protocoltype.has_modify_right(user)
-                else ""
         ]
 
 class TodoMailsTable(Table):
@@ -373,11 +381,16 @@ class DefaultMetasTable(Table):
         return ["Name", "Key", ""]
 
     def row(self, meta):
-        return [
+        user = current_user()
+        general_part = [
             meta.name,
             meta.key,
-            Table.concat([
-                Table.link(url_for("edit_defaultmeta", meta_id=meta.id), "Ändern"),
-                Table.link(url_for("delete_defaultmeta", meta_id=meta.id, confirm="Bist du dir sicher, dass du das Metadatenfeld {} löschen willst?".format(meta.name)), "Löschen")
-            ])
         ]
+        links = [
+            Table.link(url_for("edit_defaultmeta", meta_id=meta.id), "Ändern")
+        ]
+        if meta.protocoltype.has_admin_right(user):
+            links.append(Table.link(url_for("delete_defaultmeta", meta_id=meta.id, confirm="Bist du dir sicher, dass du das Metadatenfeld {} löschen willst?".format(meta.name)), "Löschen"))
+        link_part = [Table.concat(links)]
+        return general_part + link_part
+