This is an automated email from the ASF dual-hosted git repository.
gcruz pushed a commit to branch gc/8484
in repository https://gitbox.apache.org/repos/asf/allura.git
The following commit(s) were added to refs/heads/gc/8484 by this push:
new 0b494ef1b fixup! [#8484] added fediverse and instagram form fields for
projects
0b494ef1b is described below
commit 0b494ef1b8f673408d7a1d438396624d5fe8b781
Author: Guillermo Cruz <[email protected]>
AuthorDate: Tue Dec 13 15:49:40 2022 -0600
fixup! [#8484] added fediverse and instagram form fields for projects
---
Allura/allura/ext/admin/widgets.py | 12 +++++---
.../user_profile/templates/sections/social.html | 4 +++
Allura/allura/lib/helpers.py | 4 +++
Allura/allura/lib/validators.py | 34 ++++++++++++++--------
Allura/allura/lib/widgets/forms.py | 10 +++++--
Allura/allura/templates/widgets/forge_form.html | 2 +-
Allura/development.ini | 3 +-
7 files changed, 49 insertions(+), 20 deletions(-)
diff --git a/Allura/allura/ext/admin/widgets.py
b/Allura/allura/ext/admin/widgets.py
index fe8c48a0a..1c316772a 100644
--- a/Allura/allura/ext/admin/widgets.py
+++ b/Allura/allura/ext/admin/widgets.py
@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
+import tg
from tg import tmpl_context as c
import ew as ew_core
@@ -28,6 +28,7 @@ from allura.lib.widgets import forms as ff
from allura.lib.widgets import form_fields as ffw
from bson import ObjectId
+from paste.deploy.converters import aslist
class CardField(ew._Jinja2Widget):
@@ -163,7 +164,9 @@ class MetadataAdmin(ff.AdminForm):
defaults = dict(
ff.AdminForm.defaults,
enctype='multipart/form-data')
-
+ allowed_social_domains = aslist(tg.config.get('allowed_social_domains',
+ ['facebook', 'instagram',
'linkedin', 'twitter']),
+ ',')
class fields(ew_core.NameList):
name = ew.InputField(field_type='text',
label='Name',
@@ -223,9 +226,10 @@ class MetadataAdmin(ff.AdminForm):
twitter_handle = ew.InputField(
field_type="text", label='Twitter Handle')
facebook_page = ew.InputField(field_type="text", label='Facebook page',
- validator=fev.URL(add_http=True))
+
validator=formencode.All(fev.URL(add_http=True),
V.SocialDomainValidator('facebook.com')) )
instagram_page = ew.InputField(
- field_type="text", label='Instagram page',
validator=fev.URL(add_http=True))
+ field_type="text", label='Instagram page',
+ validator=formencode.All(fev.URL(add_http=True),
V.SocialDomainValidator('instagram.com')))
fediverse_address = ew.InputField(field_type="text", label="Mastodon
address",
validator=V.FediverseAddressValidator)
diff --git a/Allura/allura/ext/user_profile/templates/sections/social.html
b/Allura/allura/ext/user_profile/templates/sections/social.html
index fe7eb970f..d94f0bf48 100644
--- a/Allura/allura/ext/user_profile/templates/sections/social.html
+++ b/Allura/allura/ext/user_profile/templates/sections/social.html
@@ -33,7 +33,11 @@
{% block content %}
<dl>
{% for contact in user.get_pref('socialnetworks') %}
+ {% if contact.socialnetwork == 'Mastodon' %}
+ <dt>{{ contact.socialnetwork }}</dt><dd><a href="{{
h.parse_fediverse_address(contact.accounturl) }}" rel="me nofollow">{{
contact.accounturl }}</a></dd>
+ {% else %}
<dt>{{ contact.socialnetwork }}</dt><dd>{{
contact.accounturl|urlize(nofollow=True) }}</dd>
+ {% endif %}
{% else %}
<dd class="empty">No social networks entered.</dd>
{% endfor %}
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 6aefc5627..7e7600a3d 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -1334,3 +1334,7 @@ def pluralize_tool_name(tool_name: string, count: int):
if tool_name is not None and tool_name in pluralize_tools:
return f"{tool_name}{'s'[:count^1]}"
return tool_name
+
+def parse_fediverse_address(username: str):
+ pieces = username.split('@')
+ return f'https://{pieces[-1]}/@{pieces[1]}'
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index ea2ad9ddd..7691138ef 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -24,7 +24,7 @@ from tg import tmpl_context as c
from . import helpers as h
from datetime import datetime
import six
-from urllib.parse import urlparse
+from urllib.parse import urlsplit
from ipaddress import ip_address
import socket
@@ -52,7 +52,7 @@ class URLIsPrivate(URL):
def _to_python(self, value, state):
value = super(URLIsPrivate, self)._to_python(value, state)
- url_components = urlparse(value)
+ url_components = urlsplit(value)
try:
host_ip = socket.gethostbyname(url_components.netloc)
except socket.gaierror:
@@ -488,21 +488,31 @@ class IconValidator(fev.FancyValidator):
return value
+FEDIVERSE_REGEX = r'^@[a-zA-Z_]*@[a-zA-Z_]*\.{1}[A-Za-z]{0,10}$'
+
class FediverseAddressValidator(fev.FancyValidator):
- REGEX = r'^@[a-zA-Z_]*@[a-zA-Z_]*\.{1}[A-Za-z]{0,10}$'
- def to_python(self, value, state):
- match = re.match(FediverseAddressValidator.REGEX, value)
+
+ def _to_python(self, value, state):
+ match = re.match(FEDIVERSE_REGEX , value)
if not match:
raise fe.Invalid('Address format must be @your username@your
server', value, state)
return value.lower()
-class InstagramValidator(fev.FancyValidator):
- REGEX = r'^[a-zA-Z0-9_.]+'
- def to_python(self, value, state):
- match = re.match(InstagramValidator.REGEX, value)
- if not match:
- raise fe.Invalid("Username is not valid", value, state)
- return value
\ No newline at end of file
+
+class SocialDomainValidator(fev.FancyValidator):
+ def __init__(self, domain='', **kw):
+ self.domain = domain
+ self.domains = kw.get('domains')
+
+ def _to_python(self, value, state):
+ url = urlsplit(value)
+ if not re.match(FEDIVERSE_REGEX , value):
+ if self.domain and not self.domain ==
url.netloc.replace('www.',''):
+ raise fe.Invalid('Invalid domain for this field', value, state)
+ if self.domains and not any(domain ==
url.netloc.replace('www.','') for domain in self.domains):
+ raise fe.Invalid('Invalid domain for this field', value, state)
+ return value
+
diff --git a/Allura/allura/lib/widgets/forms.py
b/Allura/allura/lib/widgets/forms.py
index 69bf853cd..3444bf170 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -434,8 +434,12 @@ class AddSocialNetworkForm(ForgeForm):
@property
def fields(self):
socialnetworks = aslist(tg.config.get('socialnetworks',
- ['Facebook', 'Linkedin',
'Twitter', 'Google+']),
+ ['Facebook', 'Linkedin',
'Twitter',]),
',')
+ allowed_social_domains = aslist(tg.config.get('allowed_social_domains',
+ ['facebook.com',
'instagram.com', 'linkedin.com', 'twitter.com']),
+ ',')
+
return [
ew.SingleSelectField(
name='socialnetwork',
@@ -446,7 +450,9 @@ class AddSocialNetworkForm(ForgeForm):
ew.TextField(
name='accounturl',
label='Account url',
- validator=V.UnicodeString(not_empty=True))
+ validator=formencode.All(
+ V.UnicodeString(not_empty=True),
V.SocialDomainValidator(domains=allowed_social_domains)
+ ))
]
diff --git a/Allura/allura/templates/widgets/forge_form.html
b/Allura/allura/templates/widgets/forge_form.html
index 4f182d1f8..47656c9bc 100644
--- a/Allura/allura/templates/widgets/forge_form.html
+++ b/Allura/allura/templates/widgets/forge_form.html
@@ -32,7 +32,7 @@
{% set ctx=widget.context_for(field) %}
{% if field.field_type != 'hidden' %}
{% if ctx.errors and field.show_errors -%}
- <div class="grid-{{19 + extra_width}}"><span
{{widget.j2_attrs({'class':error_class})}}>{{ctx.errors|nl2br}}</span></div>
+ <div class="grid-{{19 + extra_width}}"><span
{{widget.j2_attrs({'class':error_class})}}>{{ctx.errors|nl2br}}</span></div><br>
{%- endif %}
{% if field.show_label and field.label %}
<label for="{{ctx.id}}" class="grid-4">{{field.label}}:</label>
diff --git a/Allura/development.ini b/Allura/development.ini
index 171240692..8499ef58a 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -198,7 +198,8 @@ auth.allow_birth_date = true
auth.allow_non_primary_email_password_reset = true
auth.require_email_addr = true
; List of social network options to use on user account settings
-socialnetworks = Facebook, Linkedin, Twitter, Google+
+socialnetworks = Facebook, Linkedin, Twitter, Instagram, Mastodon
+allowed_social_domains = facebook.com, instagram.com, linkedin.com, twitter.com
; Allow uploading ssh key, optionally set ssh preferences url
auth.allow_upload_ssh_key = false