]> git.ipfire.org Git - ipfire.org.git/commitdiff
users: Add index page
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 24 Jun 2023 19:15:49 +0000 (19:15 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 24 Jun 2023 19:15:49 +0000 (19:15 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/accounts.py
src/templates/people/modules/accounts-new.html [deleted file]
src/templates/people/users.html [deleted file]
src/templates/users/index.html [new file with mode: 0644]
src/templates/users/modules/list.html [new file with mode: 0644]
src/web/__init__.py
src/web/people.py
src/web/users.py

index e08d4b5d916a4aff7229e5e2bb552eb890fd5cc3..0c8213707aeade105feee42ce3e419d916299150 100644 (file)
@@ -273,8 +273,7 @@ templates_people_DATA = \
        src/templates/people/subscribed.html \
        src/templates/people/unsubscribe.html \
        src/templates/people/unsubscribed.html \
-       src/templates/people/user-edit.html \
-       src/templates/people/users.html
+       src/templates/people/user-edit.html
 
 templates_peopledir = $(templatesdir)/people
 
@@ -285,7 +284,6 @@ templates_people_messagesdir = $(templates_peopledir)/messages
 
 templates_people_modules_DATA = \
        src/templates/people/modules/accounts-list.html \
-       src/templates/people/modules/accounts-new.html \
        src/templates/people/modules/agent.html \
        src/templates/people/modules/cdr.html \
        src/templates/people/modules/channels.html \
@@ -304,10 +302,16 @@ templates_static_DATA = \
 templates_staticdir = $(templatesdir)/static
 
 templates_users_DATA = \
+       src/templates/users/index.html \
        src/templates/users/show.html
 
 templates_usersdir = $(templatesdir)/users
 
+templates_users_modules_DATA = \
+       src/templates/users/modules/list.html
+
+templates_users_modulesdir = $(templates_usersdir)/modules
+
 templates_wiki_DATA = \
        src/templates/wiki/404.html \
        src/templates/wiki/base.html \
index 5dabbef0f84ddcc9362bb828d7689e3ea39995ac..6a3cb42f6a3aa786d4b6eae51bfc351e9a174398 100644 (file)
@@ -297,6 +297,22 @@ class Accounts(Object):
        def _format_date(t):
                return t.strftime("%Y%m%d%H%M%SZ")
 
+       def get_recently_registered(self, limit=None):
+               # Check the last two weeks
+               t = datetime.datetime.utcnow() - datetime.timedelta(days=14)
+
+               # Fetch all accounts created after t
+               accounts = self.get_created_after(t)
+
+               # Order by creation date and put latest first
+               accounts.sort(key=lambda a: a.created_at, reverse=True)
+
+               # Cap at the limit
+               if accounts and limit:
+                       accounts = accounts[:limit]
+
+               return accounts
+
        def get_created_after(self, ts):
                return self._search("(&(objectClass=person)(createTimestamp>=%s))" % self._format_date(ts))
 
@@ -304,8 +320,30 @@ class Accounts(Object):
                return self._count("(&(objectClass=person)(createTimestamp>=%s))" % self._format_date(ts))
 
        def search(self, query):
-               accounts = self._search("(&(objectClass=person)(|(cn=*%s*)(uid=*%s*)(displayName=*%s*)(mail=*%s*)))" \
-                       % (query, query, query, query))
+               # Try finding an exact match
+               account = self._search_one(
+                       "(&"
+                               "(objectClass=person)"
+                               "(|"
+                                       "(uid=%s)"
+                                       "(mail=%s)"
+                                       "(mailAlternateAddress=%s)"
+                               ")"
+                       ")" % (query, query, query))
+               if account:
+                       return [account]
+
+               # Otherwise search for a substring match
+               accounts = self._search(
+                       "(&"
+                               "(objectClass=person)"
+                               "(|"
+                                       "(cn=*%s*)"
+                                       "(uid=*%s*)"
+                                       "(displayName=*%s*)"
+                                       "(mail=*%s*)"
+                               ")"
+                       ")" % (query, query, query, query))
 
                return sorted(accounts)
 
diff --git a/src/templates/people/modules/accounts-new.html b/src/templates/people/modules/accounts-new.html
deleted file mode 100644 (file)
index 5898cb7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{% if accounts %}
-    <h3>{{ _("Recently Created Accounts") }}</h3>
-
-    {% module AccountsList(accounts) %}
-{% end %}
diff --git a/src/templates/people/users.html b/src/templates/people/users.html
deleted file mode 100644 (file)
index f884102..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "../base.html" %}
-
-{% block title %}{{ _("Users") }}{% end block %}
-
-{% block content %}
-       <div class="row justify-content-center">
-               <div class="col col-md-8">
-                       <h1>{{ _("Users") }}</h1>
-
-                       {% module NewAccounts() %}
-               </div>
-       </div>
-{% end block %}
diff --git a/src/templates/users/index.html b/src/templates/users/index.html
new file mode 100644 (file)
index 0000000..c933bd5
--- /dev/null
@@ -0,0 +1,81 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Users") }}{% end block %}
+
+{% block container %}
+       <section class="hero is-dark">
+               <div class="hero-body">
+                       <div class="container">
+                               <nav class="breadcrumb is-medium" aria-label="breadcrumbs">
+                                       <ul>
+                                               <li>
+                                                       <a href="/">
+                                                               {{ _("Home") }}
+                                                       </a>
+                                               </li>
+                                               <li class="is-active">
+                                                       <a href="#" aria-current="page">{{ _("Users") }}</a>
+                                               </li>
+                                       </ul>
+                               </nav>
+
+                               <h1 class="title is-1">{{ _("Users") }}</h1>
+                       </div>
+               </div>
+       </section>
+
+       {# Search #}
+
+       <section class="section">
+               <div class="container">
+                       <div class="columns is-centered">
+                               <div class="column is-one-third">
+                                       <form action="" method="GET">
+                                               <div class="field">
+                                                       <div class="control has-icons-left">
+                                                               <input class="input is-medium" type="text"
+                                                                       name="q" {% if q %}value="{{ q }}"{% end %}
+                                                                       placeholder="{{ _("Search...") }}">
+                                                               <span class="icon is-small is-left">
+                                                                       <i class="fas fa-search"></i>
+                                                               </span>
+                                                       </div>
+                                               </div>
+                                       </form>
+                               </div>
+                       </div>
+               </div>
+       </section>
+
+       {# Search Results #}
+
+       {% if q %}
+               <section class="section">
+                       <div class="container">
+                               <h4 class="title is-4">{{ _("Search Results for '%s'") % q }}</h4>
+
+                               {% if results %}
+                                       {% module UsersList(results) %}
+                               {% else %}
+                                       <div class="notification has-text-centered">
+                                               {{ _("Nothing found for '%s'") % q }}
+                                       </div>
+                               {% end %}
+                       </div>
+               </section>
+
+       {% else %}
+               {# Recently Joined #}
+
+               {% set recently_registered = backend.accounts.get_recently_registered(limit=4) %}
+               {% if recently_registered %}
+                       <section class="section">
+                               <div class="container">
+                                       <h4 class="title is-4">{{ _("Recently Joined") }}</h4>
+
+                                       {% module UsersList(recently_registered, show_created_at=True) %}
+                               </div>
+                       </section>
+               {% end %}
+       {% end %}
+{% end block %}
diff --git a/src/templates/users/modules/list.html b/src/templates/users/modules/list.html
new file mode 100644 (file)
index 0000000..bb2f60a
--- /dev/null
@@ -0,0 +1,29 @@
+<div class="block">
+       <div class="columns is-multiline">
+               {% for account in accounts %}
+                       <div class="column is-half">
+                               <div class="box">
+                                       <div class="columns is-mobile">
+                                               <div class="column is-narrow">
+                                                       <figure class="image is-64x64">
+                                                               <img class="is-rounded" src="{{ account.avatar_url(64) }}">
+                                                       </figure>
+                                               </div>
+
+                                               <div class="column">
+                                                       <h5 class="title is-5">
+                                                               <a href="/users/{{ account.uid }}">{{ account }}</a>
+                                                       </h5>
+
+                                                       {% if show_created_at %}
+                                                               <p>
+                                                                       {{ _("Joined %s") % locale.format_date(account.created_at, shorter=True) }}
+                                                               </p>
+                                                       {% end %}
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               {% end %}
+       </div>
+</div>
index f28ff8f66a9cd7875fb5e9096b982f9b495d2797..9372efde4cccc3091dca1003491b2a4bb77c48dc 100644 (file)
@@ -75,7 +75,6 @@ class Application(tornado.web.Application):
                                "CDR"                  : people.CDRModule,
                                "Channels"             : people.ChannelsModule,
                                "MOS"                  : people.MOSModule,
-                               "NewAccounts"          : people.NewAccountsModule,
                                "Password"             : people.PasswordModule,
                                "Registrations"        : people.RegistrationsModule,
 
@@ -87,6 +86,9 @@ class Application(tornado.web.Application):
                                "FireinfoDeviceAndGroupsTable"
                                                       : fireinfo.DeviceAndGroupsTableModule,
 
+                               # Users
+                               "UsersList"            : users.ListModule,
+
                                # Wiki
                                "WikiDiff"             : wiki.WikiDiffModule,
                                "WikiNavbar"           : wiki.WikiNavbarModule,
@@ -149,6 +151,7 @@ class Application(tornado.web.Application):
                        (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
 
                        # Users
+                       (r"/users", users.IndexHandler),
                        (r"/users/([\w]+)", users.ShowHandler),
 
                        # RSS feed
@@ -301,7 +304,6 @@ class Application(tornado.web.Application):
                        (r"/groups/([a-z_][a-z0-9_-]{0,31})", people.GroupHandler),
                        (r"/register", auth.RegisterHandler),
                        (r"/search", people.SearchHandler),
-                       (r"/users", people.UsersHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", people.AvatarHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})/calls/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", people.CallHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
index 68c297344c77faaac59659990ced35a969cb1094..4a469c40c7944b00bd7868d3c4174dac11cc566b 100644 (file)
@@ -260,16 +260,6 @@ class SIPHandler(auth.CacheMixin, base.BaseHandler):
                self.render("people/sip.html", account=account)
 
 
-class UsersHandler(auth.CacheMixin, base.BaseHandler):
-       @tornado.web.authenticated
-       def get(self):
-               # Only staff can see other users
-               if not self.current_user.is_staff():
-                       raise tornado.web.HTTPError(403)
-
-               self.render("people/users.html")
-
-
 class UserEditHandler(auth.CacheMixin, base.BaseHandler):
        @tornado.web.authenticated
        def get(self, uid):
@@ -430,19 +420,6 @@ class SSODiscourse(auth.CacheMixin, base.BaseHandler):
                self.redirect("%s?%s" % (params.get("return_sso_url"), qs))
 
 
-class NewAccountsModule(ui_modules.UIModule):
-       def render(self, days=14):
-               t = datetime.datetime.utcnow() - datetime.timedelta(days=days)
-
-               # Fetch all accounts created after t
-               accounts = self.backend.accounts.get_created_after(t)
-
-               accounts.sort(key=lambda a: a.created_at, reverse=True)
-
-               return self.render_string("people/modules/accounts-new.html",
-                       accounts=accounts, t=t)
-
-
 class AccountsListModule(ui_modules.UIModule):
        def render(self, accounts=None):
                if accounts is None:
index d35448636e94e371076b968886f99d25e2a607bc..74b4d0a5a0bdaac68084bc45180ca933480f6e86 100644 (file)
@@ -4,6 +4,22 @@ import tornado.web
 
 from . import auth
 from . import base
+from . import ui_modules
+
+class IndexHandler(auth.CacheMixin, base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self):
+               results = None
+
+               # Query Term
+               q = self.get_argument("q", None)
+
+               # Peform search
+               if q:
+                       results = self.backend.accounts.search(q)
+
+               self.render("users/index.html", q=q, results=results)
+
 
 class ShowHandler(auth.CacheMixin, base.BaseHandler):
        @tornado.web.authenticated
@@ -13,3 +29,9 @@ class ShowHandler(auth.CacheMixin, base.BaseHandler):
                        raise tornado.web.HTTPError(404, "Could not find account %s" % uid)
 
                self.render("users/show.html", account=account)
+
+
+class ListModule(ui_modules.UIModule):
+       def render(self, accounts, show_created_at=False):
+               return self.render_string("users/modules/list.html", accounts=accounts,
+                       show_created_at=show_created_at)