]> git.ipfire.org Git - ipfire.org.git/commitdiff
accounts: Check emails against our local blacklist
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 24 Dec 2019 11:16:58 +0000 (12:16 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 24 Dec 2019 11:16:58 +0000 (12:16 +0100)
This list holds throwaway domains and others that cannot
be used to register an account.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/backend/accounts.py
src/templates/auth/register.html
src/web/__init__.py
src/web/auth.py

index 42d16249c42205dbe223e6ebd6fb73914fb185da..9b01223484d67249d9344799eb9bceb6edd3a345 100644 (file)
@@ -305,6 +305,21 @@ class Accounts(Object):
                # Account with uid does not exist, yet
                return False
 
+       def mail_is_blacklisted(self, mail):
+               username, delim, domain = mail.partition("@")
+
+               if domain:
+                       return self.domain_is_blacklisted(domain)
+
+       def domain_is_blacklisted(self, domain):
+               res = self.db.get("SELECT TRUE AS found FROM blacklisted_domains \
+                       WHERE domain = %s", domain)
+
+               if res and res.found:
+                       return True
+
+               return False
+
        def get_by_uid(self, uid):
                return self._search_one("(&(objectClass=person)(uid=%s))" % uid)
 
@@ -370,6 +385,10 @@ class Accounts(Object):
                if self.uid_exists(uid):
                        raise ValueError("UID exists: %s" % uid)
 
+               # Check if the email address is blacklisted
+               if self.mail_is_blacklisted(email):
+                       raise ValueError("Email is blacklisted: %s" % email)
+
                # Generate a random activation code
                activation_code = util.random_string(36)
 
index c72607a19c3ec292edc7b16c9ee512860beb0d74..313184fdb5f02f46fca91ad441267540f2eacfec 100644 (file)
                                <div class="form-group">
                                        <input type="email" class="form-control"
                                                name="email" placeholder="{{ _("Email Address") }}" required>
+                                       <div id="email-invalid" class="invalid-feedback">
+                                               {{ _("This email address cannot be used.") }}
+                                       </div>
+                                       <div id="email-taken" class="invalid-feedback">
+                                               {{ _("This email address is already in use.") }}
+                                       </div>
                                </div>
 
                                <button type="submit" class="btn btn-primary btn-block">
@@ -65,6 +71,7 @@
 {% block javascript %}
        <script>
                var check_uid;
+               var check_email;
 
                $("input[name=uid]").on("keyup", function(e) {
                        if (check_uid)
@@ -79,7 +86,7 @@
                                                uid.removeClass("is-valid is-invalid");
 
                                                // Hide all feedback
-                                               $(".invalid-feedback").hide();
+                                               uid.siblings(".invalid-feedback").hide();
 
                                                switch (data.result) {
                                                        case "ok":
                                );
                        }, 250);
                });
+
+               $("input[name=email]").on("keyup", function(e) {
+                       if (check_email)
+                               clearTimeout(check_email);
+
+                       var email = $(this);
+
+                       check_email = setTimeout(function() {
+                               $.get("/api/check/email", { email : email.val() },
+                                       function(data) {
+                                               // Reset all classes
+                                               email.removeClass("is-valid is-invalid");
+
+                                               // Hide all feedback
+                                               email.siblings(".invalid-feedback").hide();
+
+                                               switch (data.result) {
+                                                       case "ok":
+                                                               email.addClass("is-valid");
+                                                               break;
+
+                                                       case "invalid":
+                                                               email.addClass("is-invalid");
+                                                               $("#email-invalid").show();
+                                                               break;
+
+                                                       case "taken":
+                                                               email.addClass("is-invalid");
+                                                               $("#email-taken").show();
+                                                               break;
+                                               }
+                                       }
+                               );
+                       }, 250);
+               });
        </script>
 {% end block %}
index 7408496bf88e95dad571234ea8a402d5c8f6a1f3..0119d9a29de164365328323071bfe277aa33811b 100644 (file)
@@ -296,6 +296,7 @@ class Application(tornado.web.Application):
                        (r"/stats", people.StatsHandler),
 
                        # API
+                       (r"/api/check/email", auth.APICheckEmail),
                        (r"/api/check/uid", auth.APICheckUID),
                ]  + authentication_handlers)
 
index 12ae1e53b51db4b7ca76f96c231cd2a1466f5bf7..c3ef726bc99ce162754524e02b305ec79e8337f0 100644 (file)
@@ -194,7 +194,7 @@ class PasswordResetHandler(AuthenticationMixin, base.BaseHandler):
 
 
 class APICheckUID(base.APIHandler):
-       @base.ratelimit(minutes=5, requests=100)
+       @base.ratelimit(minutes=1, requests=100)
        def get(self):
                uid = self.get_argument("uid")
                result = None
@@ -212,3 +212,23 @@ class APICheckUID(base.APIHandler):
 
                # Username seems to be okay
                self.finish({ "result" : result or "ok" })
+
+
+class APICheckEmail(base.APIHandler):
+       @base.ratelimit(minutes=1, requests=100)
+       def get(self):
+               email = self.get_argument("email")
+               result = None
+
+               if not email:
+                       result = "empty"
+
+               # Check if this email address is blacklisted
+               elif self.backend.accounts.mail_is_blacklisted(email):
+                       result = "invalid"
+
+               # Check if this email address is already useed
+               elif self.backend.accounts.get_by_mail(email):
+                       result = "taken"
+
+               self.finish({ "result" : result or "ok" })