Mercurial > p > roundup > code
comparison roundup/mailgw.py @ 905:502a5ae11cc5
Very close now. The cgi and mailgw now use the new security API.
The two templates have been migrated to that setup. Lots of unit
tests. Still some issue in the web form for editing Roles assigned to
users.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 26 Jul 2002 08:27:00 +0000 |
| parents | b0d3d3535998 |
| children | 23c9d4f86380 |
comparison
equal
deleted
inserted
replaced
| 904:02763530b9e8 | 905:502a5ae11cc5 |
|---|---|
| 71 set() method to add the message to the item's spool; in the second case we | 71 set() method to add the message to the item's spool; in the second case we |
| 72 are calling the create() method to create a new node). If an auditor raises | 72 are calling the create() method to create a new node). If an auditor raises |
| 73 an exception, the original message is bounced back to the sender with the | 73 an exception, the original message is bounced back to the sender with the |
| 74 explanatory message given in the exception. | 74 explanatory message given in the exception. |
| 75 | 75 |
| 76 $Id: mailgw.py,v 1.78 2002-07-25 07:14:06 richard Exp $ | 76 $Id: mailgw.py,v 1.79 2002-07-26 08:26:59 richard Exp $ |
| 77 ''' | 77 ''' |
| 78 | 78 |
| 79 | 79 |
| 80 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri | 80 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri |
| 81 import time, random | 81 import time, random |
| 91 pass | 91 pass |
| 92 | 92 |
| 93 class MailUsageHelp(Exception): | 93 class MailUsageHelp(Exception): |
| 94 pass | 94 pass |
| 95 | 95 |
| 96 class UnAuthorized(Exception): | 96 class Unauthorized(Exception): |
| 97 """ Access denied """ | 97 """ Access denied """ |
| 98 | 98 |
| 99 def initialiseSecurity(security): | 99 def initialiseSecurity(security): |
| 100 ''' Create some Permissions and Roles on the security object | 100 ''' Create some Permissions and Roles on the security object |
| 101 | 101 |
| 102 This function is directly invoked by security.Security.__init__() | 102 This function is directly invoked by security.Security.__init__() |
| 103 as a part of the Security object instantiation. | 103 as a part of the Security object instantiation. |
| 104 ''' | 104 ''' |
| 105 newid = security.addPermission(name="Email Registration", | 105 newid = security.addPermission(name="Email Registration", |
| 106 description="Anonymous may register through e-mail") | 106 description="Anonymous may register through e-mail") |
| 107 security.addPermissionToRole('Anonymous', newid) | |
| 108 | 107 |
| 109 class Message(mimetools.Message): | 108 class Message(mimetools.Message): |
| 110 ''' subclass mimetools.Message so we can retrieve the parts of the | 109 ''' subclass mimetools.Message so we can retrieve the parts of the |
| 111 message... | 110 message... |
| 112 ''' | 111 ''' |
| 180 m = [''] | 179 m = [''] |
| 181 m.append(str(value)) | 180 m.append(str(value)) |
| 182 m.append('\n\nMail Gateway Help\n=================') | 181 m.append('\n\nMail Gateway Help\n=================') |
| 183 m.append(fulldoc) | 182 m.append(fulldoc) |
| 184 m = self.bounce_message(message, sendto, m) | 183 m = self.bounce_message(message, sendto, m) |
| 185 except UnAuthorized, value: | 184 except Unauthorized, value: |
| 186 # just inform the user that he is not authorized | 185 # just inform the user that he is not authorized |
| 187 sendto = [sendto[0][1]] | 186 sendto = [sendto[0][1]] |
| 188 m = [''] | 187 m = [''] |
| 189 m.append(str(value)) | 188 m.append(str(value)) |
| 190 m = self.bounce_message(message, sendto, m) | 189 m = self.bounce_message(message, sendto, m) |
| 520 | 519 |
| 521 # | 520 # |
| 522 # handle the users | 521 # handle the users |
| 523 # | 522 # |
| 524 | 523 |
| 525 # Don't create users if ANONYMOUS_REGISTER_MAIL is denied | 524 # Don't create users if anonymous isn't allowed to register |
| 526 # ... fall back on ANONYMOUS_REGISTER if the other doesn't exist | |
| 527 create = 1 | 525 create = 1 |
| 528 if hasattr(self.instance, 'ANONYMOUS_REGISTER_MAIL'): | 526 anonid = self.db.user.lookup('anonymous') |
| 529 if self.instance.ANONYMOUS_REGISTER_MAIL == 'deny': | 527 if not self.db.security.hasPermission('Email Registration', anonid): |
| 530 create = 0 | |
| 531 elif self.instance.ANONYMOUS_REGISTER == 'deny': | |
| 532 create = 0 | 528 create = 0 |
| 533 | 529 |
| 534 author = self.db.uidFromAddress(message.getaddrlist('from')[0], | 530 author = uidFromAddress(self.db, message.getaddrlist('from')[0], |
| 535 create=create) | 531 create=create) |
| 536 if not author: | 532 if not author: |
| 537 raise UnAuthorized, ''' | 533 raise Unauthorized, ''' |
| 538 You are not a registered user. | 534 You are not a registered user. |
| 539 | 535 |
| 540 Unknown address: %s | 536 Unknown address: %s |
| 541 '''%message.getaddrlist('from')[0][1] | 537 '''%message.getaddrlist('from')[0][1] |
| 542 | 538 |
| 559 if r == tracker_email or not r: | 555 if r == tracker_email or not r: |
| 560 continue | 556 continue |
| 561 | 557 |
| 562 # look up the recipient - create if necessary (and we're | 558 # look up the recipient - create if necessary (and we're |
| 563 # allowed to) | 559 # allowed to) |
| 564 recipient = self.db.uidFromAddress(recipient, create) | 560 recipient = uidFromAddress(self.db, recipient, create) |
| 565 | 561 |
| 566 # if all's well, add the recipient to the list | 562 # if all's well, add the recipient to the list |
| 567 if recipient: | 563 if recipient: |
| 568 recipients.append(recipient) | 564 recipients.append(recipient) |
| 569 | 565 |
| 729 # commit the changes to the DB | 725 # commit the changes to the DB |
| 730 self.db.commit() | 726 self.db.commit() |
| 731 | 727 |
| 732 return nodeid | 728 return nodeid |
| 733 | 729 |
| 730 def extractUserFromList(userClass, users): | |
| 731 '''Given a list of users, try to extract the first non-anonymous user | |
| 732 and return that user, otherwise return None | |
| 733 ''' | |
| 734 if len(users) > 1: | |
| 735 for user in users: | |
| 736 # make sure we don't match the anonymous or admin user | |
| 737 if userClass.get(user, 'username') in ('admin', 'anonymous'): | |
| 738 continue | |
| 739 # first valid match will do | |
| 740 return user | |
| 741 # well, I guess we have no choice | |
| 742 return user[0] | |
| 743 elif users: | |
| 744 return users[0] | |
| 745 return None | |
| 746 | |
| 747 def uidFromAddress(db, address, create=1): | |
| 748 ''' address is from the rfc822 module, and therefore is (name, addr) | |
| 749 | |
| 750 user is created if they don't exist in the db already | |
| 751 ''' | |
| 752 (realname, address) = address | |
| 753 | |
| 754 # try a straight match of the address | |
| 755 user = extractUserFromList(db.user, db.user.stringFind(address=address)) | |
| 756 if user is not None: return user | |
| 757 | |
| 758 # try the user alternate addresses if possible | |
| 759 props = db.user.getprops() | |
| 760 if props.has_key('alternate_addresses'): | |
| 761 users = db.user.filter(None, {'alternate_addresses': address}, | |
| 762 [], []) | |
| 763 user = extractUserFromList(db.user, users) | |
| 764 if user is not None: return user | |
| 765 | |
| 766 # try to match the username to the address (for local | |
| 767 # submissions where the address is empty) | |
| 768 user = extractUserFromList(db.user, db.user.stringFind(username=address)) | |
| 769 | |
| 770 # couldn't match address or username, so create a new user | |
| 771 if create: | |
| 772 return db.user.create(username=address, address=address, | |
| 773 realname=realname, roles=db.config.NEW_EMAIL_USER_ROLES) | |
| 774 else: | |
| 775 return 0 | |
| 776 | |
| 734 def parseContent(content, keep_citations, keep_body, | 777 def parseContent(content, keep_citations, keep_body, |
| 735 blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'), | 778 blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'), |
| 736 eol=re.compile(r'[\r\n]+'), | 779 eol=re.compile(r'[\r\n]+'), |
| 737 signature=re.compile(r'^[>|\s]*[-_]+\s*$'), | 780 signature=re.compile(r'^[>|\s]*[-_]+\s*$'), |
| 738 original_message=re.compile(r'^[>|\s]*-----Original Message-----$')): | 781 original_message=re.compile(r'^[>|\s]*-----Original Message-----$')): |
| 798 content = '\n\n'.join(l) | 841 content = '\n\n'.join(l) |
| 799 return summary, content | 842 return summary, content |
| 800 | 843 |
| 801 # | 844 # |
| 802 # $Log: not supported by cvs2svn $ | 845 # $Log: not supported by cvs2svn $ |
| 846 # Revision 1.78 2002/07/25 07:14:06 richard | |
| 847 # Bugger it. Here's the current shape of the new security implementation. | |
| 848 # Still to do: | |
| 849 # . call the security funcs from cgi and mailgw | |
| 850 # . change shipped templates to include correct initialisation and remove | |
| 851 # the old config vars | |
| 852 # ... that seems like a lot. The bulk of the work has been done though. Honest :) | |
| 853 # | |
| 803 # Revision 1.77 2002/07/18 11:17:31 gmcm | 854 # Revision 1.77 2002/07/18 11:17:31 gmcm |
| 804 # Add Number and Boolean types to hyperdb. | 855 # Add Number and Boolean types to hyperdb. |
| 805 # Add conversion cases to web, mail & admin interfaces. | 856 # Add conversion cases to web, mail & admin interfaces. |
| 806 # Add storage/serialization cases to back_anydbm & back_metakit. | 857 # Add storage/serialization cases to back_anydbm & back_metakit. |
| 807 # | 858 # |
