templates_people_modulesdir = $(templates_peopledir)/modules
+templates_people_ssh_keys_DATA = \
+ src/templates/people/ssh-keys/base.html \
+ src/templates/people/ssh-keys/index.html
+
+templates_people_ssh_keysdir = $(templates_peopledir)/ssh-keys
+
templates_static_DATA = \
src/templates/static/chat.html \
src/templates/static/features.html \
import ldap.modlist
import logging
import phonenumbers
+import sshpubkeys
import urllib.parse
import urllib.request
def upload_avatar(self, avatar):
self._set("jpegPhoto", avatar)
+ # SSH Keys
+
+ @lazy_property
+ def ssh_keys(self):
+ ret = []
+
+ for key in self._get_strings("sshPublicKey"):
+ s = sshpubkeys.SSHKey()
+
+ try:
+ s.parse(key)
+ except (sshpubkeys.InvalidKeyError, NotImplementedError) as e:
+ logging.warning("Could not parse SSH key %s: %s" % (key, e))
+ continue
+
+ ret.append(s)
+
+ return ret
if __name__ == "__main__":
a = Accounts()
}
}
+.list-group {
+ .list-group-item {
+ @extend .inverse;
+ }
+}
+
.nav {
.nav-link {
color: $white;
--- /dev/null
+{% extends "../user-base.html" %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ account }} - {{ _("SSH Keys") }}{% end block %}
+
+{% block main %}
+ <h1>{{ _("SSH Keys") }}</h1>
+
+ <ul class="list-group mb-3">
+ {% for key in account.ssh_keys %}
+ <li class="list-group-item">
+ <h5 class="mb-1">
+ <a class="text-dark" href="/users/{{ account.uid }}/ssh-keys/{{ key.hash_md5() }}">
+ {{ key.comment or _("%s Key") % key.key_type.decode() }}
+ </a>
+ </h5>
+
+ <p class="text-monospace mb-0">{{ key.hash_md5() }}</p>
+
+ {% if key.options %}
+ <p class="my-1">{{ _("Options") }}</p>
+
+ <ul class="mb-0">
+ {% for option, values in sorted(key.options.items()) %}
+ <li class="small">
+ <span class="text-monospace">{{ option }}</span>
+
+ {% if not values == [True] %}
+ = <span class="text-monospace">{{ "".join(values) }}</span>
+ {% end %}
+ </li>
+ {% end %}
+ </ul>
+ {% end %}
+
+ {% if account.can_be_managed_by(current_user) %}
+ <a class="btn btn-outline-danger btn-sm btn-block mt-2" href="/users/{{ account.uid }}/ssh-keys/{{ key.hash_md5() }}/delete">
+ {{ _("Delete") }}
+ </a>
+ {% end %}
+ </li>
+ {% end %}
+ </ul>
+
+ {% if account.can_be_managed_by(current_user) %}
+ <a class="btn btn-success btn-block" href="/users/{{ account.uid }}/ssh-keys/upload">
+ {{ _("Upload New SSH Key") }}
+ </a>
+ {% end %}
+{% end block %}
</h5>
{% end %}
- {% if account.can_be_managed_by(current_user) %}
- <div class="btn-toolbar mb-3">
+ <div class="btn-toolbar mb-3">
+ <a class="btn btn-light btn-sm btn-block" href="/users/{{ account.uid }}/ssh-keys">
+ <span class="fas fa-key mr-2"></span> {{ _("SSH Keys") }}
+ </a>
+
+ {% if account.can_be_managed_by(current_user) %}
<a class="btn btn-warning btn-sm btn-block" href="/users/{{ account.uid }}/edit">
<span class="fas fa-edit mr-2"></span> {{ _("Edit") }}
</a>
<a class="btn btn-light btn-sm btn-block" href="/users/{{ account.uid }}/passwd">
{{ _("Change Password") }}
</a>
-
- <a class="btn btn-light btn-sm btn-block" href="/users/{{ account.uid }}/ssh-keys">
- <span class="fas fa-key mr-2"></span> {{ _("Manage SSH Keys") }}
- </a>
- </div>
- {% end %}
+ {% end %}
+ </div>
</div>
{% end %}
(r"/users/(\w+)/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
(r"/users/(\w+)/edit", people.UserEditHandler),
(r"/users/(\w+)/passwd", people.UserPasswdHandler),
+ (r"/users/(\w+)/ssh-keys", people.SSHKeysIndexHandler),
(r"/users/(\w+)/sip", people.SIPHandler),
] + authentication_handlers)
self.render("people/search.html", q=q, accounts=accounts)
+class SSHKeysIndexHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, uid):
+ account = self.backend.accounts.get_by_uid(uid)
+ if not account:
+ raise tornado.web.HTTPError(404, "Could not find account %s" % uid)
+
+ self.render("people/ssh-keys/index.html", account=account)
+
+
class SIPHandler(base.BaseHandler):
@tornado.web.authenticated
def get(self, uid):