Skip to content

Commit b0ddd0d

Browse files
committed
Added models for mailman lists and subscribed and whitelisted addresses, and an import management command suited to be run as a periodic cron-job.
- Legacy-Id: 11373
1 parent c6e1daa commit b0ddd0d

10 files changed

Lines changed: 215 additions & 0 deletions

File tree

ietf/mailinglists/admin.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright The IETF Trust 2016, All Rights Reserved
2+
3+
from django.contrib import admin
4+
5+
from ietf.mailinglists.models import List, Subscribed, Whitelisted
6+
7+
8+
class ListAdmin(admin.ModelAdmin):
9+
list_display = ('id', 'name', 'description', 'advertised')
10+
search_fields = ('name',)
11+
admin.site.register(List, ListAdmin)
12+
13+
14+
class SubscribedAdmin(admin.ModelAdmin):
15+
list_display = ('id', 'time', 'address')
16+
raw_id_fields = ('lists',)
17+
search_fields = ('address',)
18+
admin.site.register(Subscribed, SubscribedAdmin)
19+
20+
21+
class WhitelistedAdmin(admin.ModelAdmin):
22+
list_display = ('id', 'time', 'address', 'by')
23+
admin.site.register(Whitelisted, WhitelistedAdmin)

ietf/mailinglists/management/__init__.py

Whitespace-only changes.

ietf/mailinglists/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright The IETF Trust 2016, All Rights Reserved
2+
3+
import sys
4+
from textwrap import dedent
5+
6+
import debug # pyflakes:ignore
7+
8+
from django.conf import settings
9+
from django.core.management.base import BaseCommand
10+
11+
from ietf.mailinglists.models import List, Subscribed
12+
13+
class Command(BaseCommand):
14+
"""
15+
Import list information from Mailman.
16+
17+
Import announced list names, descriptions, and subscribers, by calling the
18+
appropriate Mailman functions and adding entries to the database.
19+
20+
Run this from cron regularly, with sufficient permissions to access the
21+
mailman database files.
22+
23+
"""
24+
25+
help = dedent(__doc__).strip()
26+
27+
#option_list = BaseCommand.option_list + ( )
28+
29+
def note(self, msg):
30+
if self.verbosity > 1:
31+
self.stdout.write(msg)
32+
33+
def handle(self, *filenames, **options):
34+
"""
35+
36+
* Import announced lists, with appropriate meta-information.
37+
38+
* For each list, import the members.
39+
40+
"""
41+
42+
self.verbosity = int(options.get('verbosity'))
43+
44+
sys.path.append(settings.MAILMAN_LIB_DIR)
45+
46+
from Mailman import Utils
47+
from Mailman import MailList
48+
49+
for name in Utils.list_names():
50+
mlist = MailList.MailList(name, lock=False)
51+
self.note("List: %s" % mlist.internal_name())
52+
if mlist.advertised:
53+
list, created = List.objects.get_or_create(name=mlist.real_name, description=mlist.description, advertised=mlist.advertised)
54+
# The following calls return lowercased addresses
55+
members = mlist.getRegularMemberKeys() + mlist.getDigestMemberKeys()
56+
known = [ s.address for s in Subscribed.objects.filter(lists__name=name) ]
57+
for addr in members:
58+
if not addr in known:
59+
self.note(" Adding subscribed: %s" % (addr))
60+
new, created = Subscribed.objects.get_or_create(address=addr)
61+
new.lists.add(list)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from django.db import migrations
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [
8+
]
9+
10+
operations = [
11+
]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import models, migrations
5+
import django.core.validators
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('person', '0014_auto_20160613_0751'),
12+
('mailinglists', '0001_initial'),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name='List',
18+
fields=[
19+
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
20+
('name', models.CharField(max_length=32)),
21+
('description', models.CharField(max_length=256)),
22+
('advertised', models.BooleanField(default=True)),
23+
],
24+
options={
25+
},
26+
bases=(models.Model,),
27+
),
28+
migrations.CreateModel(
29+
name='Subscribed',
30+
fields=[
31+
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
32+
('time', models.DateTimeField(auto_now_add=True)),
33+
('address', models.CharField(max_length=64, validators=[django.core.validators.EmailValidator()])),
34+
('lists', models.ManyToManyField(to='mailinglists.List')),
35+
],
36+
options={
37+
},
38+
bases=(models.Model,),
39+
),
40+
migrations.CreateModel(
41+
name='Whitelisted',
42+
fields=[
43+
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
44+
('time', models.DateTimeField(auto_now_add=True)),
45+
('address', models.CharField(max_length=64, validators=[django.core.validators.EmailValidator()])),
46+
('by', models.ForeignKey(to='person.Person')),
47+
],
48+
options={
49+
},
50+
bases=(models.Model,),
51+
),
52+
]

ietf/mailinglists/migrations/__init__.py

Whitespace-only changes.

ietf/mailinglists/resources.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright The IETF Trust 2016, All Rights Reserved
2+
# Autogenerated by the makeresources management command 2016-06-12 12:29 PDT
3+
from tastypie.resources import ModelResource
4+
from tastypie.fields import ToManyField # pyflakes:ignore
5+
from tastypie.constants import ALL, ALL_WITH_RELATIONS # pyflakes:ignore
6+
from tastypie.cache import SimpleCache
7+
8+
from ietf import api
9+
from ietf.api import ToOneField # pyflakes:ignore
10+
11+
from ietf.mailinglists.models import Whitelisted, List, Subscribed
12+
13+
14+
from ietf.person.resources import PersonResource
15+
class WhitelistedResource(ModelResource):
16+
by = ToOneField(PersonResource, 'by')
17+
class Meta:
18+
queryset = Whitelisted.objects.all()
19+
serializer = api.Serializer()
20+
cache = SimpleCache()
21+
#resource_name = 'whitelisted'
22+
filtering = {
23+
"id": ALL,
24+
"time": ALL,
25+
"address": ALL,
26+
"by": ALL_WITH_RELATIONS,
27+
}
28+
api.mailinglists.register(WhitelistedResource())
29+
30+
class ListResource(ModelResource):
31+
class Meta:
32+
queryset = List.objects.all()
33+
serializer = api.Serializer()
34+
cache = SimpleCache()
35+
#resource_name = 'list'
36+
filtering = {
37+
"id": ALL,
38+
"name": ALL,
39+
"description": ALL,
40+
"advertised": ALL,
41+
}
42+
api.mailinglists.register(ListResource())
43+
44+
class SubscribedResource(ModelResource):
45+
lists = ToManyField(ListResource, 'lists', null=True)
46+
class Meta:
47+
queryset = Subscribed.objects.all()
48+
serializer = api.Serializer()
49+
cache = SimpleCache()
50+
#resource_name = 'subscribed'
51+
filtering = {
52+
"id": ALL,
53+
"time": ALL,
54+
"address": ALL,
55+
"lists": ALL_WITH_RELATIONS,
56+
}
57+
api.mailinglists.register(SubscribedResource())
58+

ietf/mailinglists/tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Copyright The IETF Trust 2016, All Rights Reserved
2+
13
from django.core.urlresolvers import reverse as urlreverse
24

35
from pyquery import PyQuery

ietf/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,14 @@ def skip_unreadable_post(record):
650650
}
651651
}
652652

653+
MAILMAN_LIB_DIR = '/usr/lib/mailman'
654+
655+
# This is the number of seconds required between subscribing to an ietf
656+
# mailing list and datatracker account creation being accepted
657+
LIST_ACCOUNT_DELAY = 60*60*25 # 25 hours
658+
ACCOUNT_REQUEST_EMAIL = 'account-request@ietf.org'
659+
660+
653661
# Put the production SECRET_KEY in settings_local.py, and also any other
654662
# sensitive or site-specific changes. DO NOT commit settings_local.py to svn.
655663
from settings_local import * # pyflakes:ignore

0 commit comments

Comments
 (0)