コード例 #1
0
def test__mail__MailAssignmentPreview_1(browser):
    """It can send Fehlende Arbeitsstunden."""
    from sw.allotmentclub import Message, User, Member, Assignment
    from sw.allotmentclub import AssignmentAttendee
    from sw.allotmentclub.conftest import import_members
    import_members()
    assignment = Assignment.find_or_create(
        day=datetime.now(),
        accounting_year=datetime.now().year
    )
    AssignmentAttendee.find_or_create(
        assignment=assignment,
        member=Member.query().filter(Member.lastname == 'Wehrmann').one(),
        hours=5)  # No letter
    AssignmentAttendee.find_or_create(
        assignment=assignment,
        member=Member.query().filter(Member.lastname == 'Hennig').one(),
        hours=3)  # Needs to pay less

    verein = Member.find_or_create(lastname="Verein")
    Message.create(id=245, members=[verein], user=User.create(),
                   accounting_year=2018,
                   subject="Fehlende Arbeitsstunden",
                   body=MISSING_ASSIGMENT_BODY)
    transaction.commit()
    browser.login()
    with mock.patch('sw.allotmentclub.browser.letter.datetime') as dt:
        dt.now.return_value = datetime(2016, 3, 25)
        browser.open('http://localhost/mail/245/preview')
    assertFileEqual(browser.contents, 'test_mail_fehlarbeitsstunden_1.pdf')
コード例 #2
0
def setUp():
    from sw.allotmentclub import Depot, User
    user = User.create(username='******')
    Depot.create(date=datetime.datetime(2014, 11, 27, 7, 21, 45),
                 size=15, data=b'GIF89a????!?,D;', mimetype='image/gif',
                 name='test.gif', user=user)
    transaction.commit()
コード例 #3
0
def test__mail__get_recipient_3(database, setUp):
    """It returns lastname and firstname of external recipient."""
    from sw.allotmentclub import ExternalRecipient, Message, User
    from ..mail import get_recipient
    muster = ExternalRecipient.create(lastname="Muster", firstname="Max")
    Message.create(id=300, externals=[muster], user=User.get(1))
    assert get_recipient(300) == "Muster, Max"
コード例 #4
0
ファイル: home.py プロジェクト: sweh/sw.allotmentclub.backend
 def __call__(self):
     result = super(HomeView, self).__call__()
     last = None
     timeline = []
     for date, user_id, type_, msg in sw.allotmentclub.json_result(
             result['data']['data']):
         if timeline:
             last = timeline[-1]
         time = format_date(date)
         user = User.get(user_id)
         username = user.username
         if last and last['username'] == username and last['time'] == time:
             if msg == last['detail'][-1]:
                 continue
             last['detail'].append(msg)
         else:
             item = {
                 'time': time,
                 'username': username,
                 'firstname': user.vorname,
                 'lastname': user.nachname,
                 'detail': [msg]
             }
             if username == 'system':
                 item['fa_icon'] = 'fa-gear'
             else:
                 item['gravatar_url'] = (
                     'https://www.gravatar.com/avatar/%s' % (
                         hashlib.md5(
                             user.email.encode('utf-8')).hexdigest()))
             timeline.append(item)
     result['data']['timeline'] = timeline
     return result
コード例 #5
0
def test__mail__get_recipient_4(database, setUp):
    """It returns Mehrere Empfänger if multiple recipients."""
    from sw.allotmentclub import ExternalRecipient, Message, User
    from ..mail import get_recipient
    muster = ExternalRecipient.create(lastname="Muster", firstname="Max")
    muster2 = ExternalRecipient.create(lastname="Mustermann", firstname="Max")
    Message.create(id=300, externals=[muster, muster2], user=User.get(1))
    assert get_recipient(300) == "Mehrere Empfänger"
コード例 #6
0
def test__mail__MailPreviewView_3(browser):
    """It does not print address and date if no member assigned to message."""
    from sw.allotmentclub import Message, User
    Message.create(id=244, user=User.create(), accounting_year=2015,
                   subject="Info-Brief", body="**Info** an alle Mitglieder")
    transaction.commit()
    browser.login()
    browser.open('http://localhost/mail/244/preview')
    assertFileEqual(browser.contents, 'test_mail_preview_3.pdf')
コード例 #7
0
def user(request, organization, database):
    """Fixture creating a user with no role."""
    user = User.find_or_create(username='******',
                               password='******',
                               nachname='Mittag',
                               position='Vorsitzender',
                               ort='Leuna',
                               organization_id=1)
    database.session.flush()
    return user
コード例 #8
0
def test_displays_list_of_log_entries(browser):
    from sw.allotmentclub import Log, User
    User.create(id=2, username='******', vorname='Sebastian',
                nachname='Wehrmann')
    Log.create(user_id=2, name='user data', level='INFO',
               created=datetime.datetime.now(), msg='Test-Log-Eintrag')
    transaction.commit()

    browser.login()
    browser.open('http://localhost/')
    assert {
        'username': '******',
        'firstname': 'Sebastian',
        'lastname': 'Wehrmann',
        'gravatar_url': 'https://www.gravatar.com/avatar/'
                        'd41d8cd98f00b204e9800998ecf8427e',
        'detail': ['Test-Log-Eintrag'],
        'time': 'gerade eben'
    } in browser.json['data']['timeline']
コード例 #9
0
def setUp():
    from sw.allotmentclub import Member, Message, User, SentMessageInfo
    mustermann = Member.create(lastname="Mustermann", firstname="Max",
                               email='*****@*****.**')
    user = User.create(username='******')
    msg = Message.create(id=242, members=[mustermann], user=user,
                         accounting_year=2016, subject="Test", body="")
    SentMessageInfo.create(message=msg, tag='*****@*****.**',
                           address='*****@*****.**')
    transaction.commit()
コード例 #10
0
def verwalter(request, organization, database):
    """Fixture creating a user with role Administrator."""
    user = User.find_or_create(username='******',
                               password='******',
                               vorname='Admin',
                               nachname='istrator',
                               unrestricted_access=True,
                               organization_id=1)
    database.session.flush()
    transaction.commit()
    return user
コード例 #11
0
def test_fa_icon_if_system_user(browser):
    from sw.allotmentclub import Log, User
    user = User.find_or_create(username='******')
    Log.create(user=user, name='user data', level='INFO',
               created=datetime.datetime.now(), msg='Test-Log-Eintrag')
    transaction.commit()

    browser.login()
    browser.open('http://localhost/')
    timeline = browser.json['data']['timeline'][0]
    assert timeline['fa_icon'] == 'fa-gear'
    assert 'gravatar_url' not in timeline
コード例 #12
0
def test__mail__MailPreviewView_4(browser, setUp):
    """It renders attachments to the message."""
    from sw.allotmentclub import Attachment, User
    import pkg_resources
    data = pkg_resources.resource_stream(
        'sw.allotmentclub.browser.tests', 'test_protocol_print.pdf').read()
    Attachment.create(message_id=243, data=data, mimetype='application/pdf',
                      user=User.get(1))
    transaction.commit()
    browser.login()
    with mock.patch('sw.allotmentclub.browser.letter.datetime') as dt:
        dt.now.return_value = datetime(2016, 3, 25)
        browser.open('http://localhost/mail/243/preview')
    assertFileEqual(browser.contents, 'test_mail_preview_4.pdf')
コード例 #13
0
def test_send_mail_sends_text_mail(mailer, database):
    from ..letter import send_mail
    user = User.create(username='******', vorname='Hans', nachname='Wurst')
    send_mail('*****@*****.**', 'Betreff', 'Dies ist der Inhalt', user)
    assert 1 == len(mailer.outbox)
    message = mailer.outbox[0]
    assert ('Vorstand Leuna-Bungalowgemeinschaft Roter See '
            '<*****@*****.**>' == message.sender)
    assert ['*****@*****.**'] == message.recipients
    assert message.body == (
        '\nDies ist der Inhalt\n\nMit freundlichen Grüßen,\n'
        'Im Auftrag des Vorstandes\n\nHans Wurst (None)\n\n')
    assert message.html is None
    assert 'Anschreiben.pdf' == message.attachments[0].filename
コード例 #14
0
def test__mail__MailElectricityPreview_1(browser):
    """It can send Energieabrechnungen."""
    from sw.allotmentclub import Message, User, Member
    from sw.allotmentclub.conftest import import_energy_meters, import_members
    import_members()
    import_energy_meters()
    verein = Member.find_or_create(lastname="Verein")
    Message.create(id=245, members=[verein], user=User.create(),
                   accounting_year=2014, subject="Energieabrechnung",
                   body=ENERGIEABRECHNUNG_BODY)
    transaction.commit()
    browser.login()
    with mock.patch('sw.allotmentclub.browser.letter.datetime') as dt:
        dt.now.return_value = datetime(2016, 3, 25)
        browser.open('http://localhost/mail/245/preview')
    assertFileEqual(browser.contents, 'test_mail_energieabrechnung_1.pdf')
コード例 #15
0
def setUp():
    from sw.allotmentclub import Member, Message, User
    verein = Member.create(lastname="Verein")
    mustermann = Member.create(lastname="Mustermann", firstname="Max")
    user = User.create(username='******')
    greeting = ('Sehr geehrte{{deflection}} {{appellation}} '
                '{{title}} {{lastname}},\n\n')
    Message.create(id=242, members=[verein], user=user, accounting_year=2015,
                   subject="Info-Brief",
                   body=greeting+"**Info** an alle Mitglieder")
    Message.create(id=243, members=[mustermann], user=user,
                   accounting_year=2015, subject="Willkommen",
                   body=greeting+"Willkommen im Verein.")
    Message.create(id=244, members=[mustermann], user=user,
                   accounting_year=2016, subject="Beitragsabrechnung",
                   body=greeting)
    transaction.commit()
コード例 #16
0
def login(login, password):
    """Try to verify the user.

    Returns (User, authenticated?)

    User will be None if password is missing or user does not exist,
    otherwise the object will be retrieved from the database.

    authenticated? will be True iff check_password succeeds
    and False otherwise.
    """
    user = None
    if login:
        user = User.by_username(login)
    if user and password:
        return (user, user.check_password(password))

    return (None, False)
コード例 #17
0
def setUp():
    from sw.allotmentclub import Bulletin, User
    user = User.create(username='******')
    Bulletin.create(
        date=datetime.datetime(2015, 3, 7, 10),
        subject='Ruhezeiten im Verein',
        user=user,
        content="""
### Mittagsruhe

- täglich 13.00 - 15.00 Uhr (ganzjährig)

### Nachtruhe

- Montag bis Freitag:      22.00 - 08.00 Uhr
- Samstag &amp; Sonntag:    24.00 - 08.00 Uhr

### Genereller Baustop

- jährlich vom 15. Juni bis 31. August.""")
    transaction.commit()
コード例 #18
0
def import_transactions():
    parser = gocept.logging.ArgumentParser(
        description="Import banking transactions.")
    parser.add_argument('-c',
                        '--config',
                        default='portal.ini',
                        help='Specify the config file. (default: portal.ini)')
    options = parser.parse_args()
    app = Application.from_filename(options.config)
    registry = pyramid.registry.Registry(
        bases=(zope.component.getGlobalSiteManager(), ))
    config = pyramid.config.Configurator(settings=app.settings,
                                         registry=registry)
    config.setup_registry(settings=app.settings)
    request = pyramid.testing.DummyRequest(_registry=registry)
    request.client_addr = '127.0.0.1'
    context = pyramid.threadlocal.manager.get().copy()
    context['request'] = request
    context['registry'] = registry
    pyramid.threadlocal.manager.push(context)
    user = User.by_username('system')
    import_transactions_from_fints(user)
コード例 #19
0
    def send_report(self):
        org_id = self.request.user.organization_id
        current_year = get_selected_year()
        price = (EnergyPrice.query().filter(
            EnergyValue.organization_id == org_id).filter(
                EnergyPrice.year == current_year).one())

        data = json.loads(json.dumps(price))
        data['phases'] = self.phases
        data['price'] = format_eur(data['price'])
        data['bill'] = format_eur(data['bill'])
        data['normal_fee'] = format_eur(data['normal_fee'])
        data['power_fee'] = format_eur(data['power_fee'])

        subject = "Bericht Energieabrechnung {year}".format(**data)

        body = """
        <p>Sehr geehrter Vorstand,</p>

        <p>anbei die Kennzahlen zur diesjährigen Energieabrechnung:</p>

        <table>
        <tr><td>Verbrauch Hauptzähler: </td><td>{usage_hauptzaehler} kWh</td></tr>
        <tr><td>Verbrauch der Mitglieder (inkl. SAT-Anlage und
        Vereinsgebäude): </td><td>{usage_members} kWh</td></tr>
        <tr><td colspan=2></td></tr>

        <tr><td>Verluststrom: </td><td>{usage_hauptzaehler} kWh - {usage_members} kWh = {leakage_current} kWh</td></tr>
        <tr><td colspan=2></td></tr>

        <tr><td>Preis pro kWh: </td><td>{bill} / {usage_hauptzaehler} kWh = {price}/kWh</td></tr>
        <tr><td colspan=2></td></tr>

        <tr><td>Grundgebühr 1 Phase ({phases} insgesamt): </td><td>{leakage_current} kWh * {price}/kWh / {phases} = {normal_fee}</td></tr>
        <tr><td>Grundgebühr einfacher Zähler (1 Phase): </td><td>{normal_fee}</td></tr>
        <tr><td>Grundgebühr Kraftstromzähler (3 Phase): </td><td>{power_fee}</td></tr>
        </table><br /><br />""".format(**data)  # noqa
        send_mail("*****@*****.**", subject, body,
                  User.by_username('system'))
コード例 #20
0
 def __call__(self):
     data = self.request.json
     sender = data['FromFull']['Email'].lower()
     if sender == '*****@*****.**':
         return Response('ok')
     if data['Subject'].startswith('***** SPAM'):
         return Response('ok')
     message = Message.create(inbound=True,
                              organization_id=self.organization_id,
                              user=User.by_username('system'))
     member = Member.query().filter(Member.email == sender).first()
     if member:
         message.members.append(member)
         message.organization_id = member.organization_id
     else:
         external = (ExternalRecipient.query().filter(
             ExternalRecipient.email == sender).first())
         if not external:
             external = ExternalRecipient.create(email=sender)
             external.lastname = data['FromFull']['Name']
             external.organization_id = self.organization_id
         message.externals.append(external)
         message.organization_id = external.organization_id
     message.subject = data['Subject']
     message.body = (data['HtmlBody']
                     if data['HtmlBody'] else data['TextBody'])
     message.sent = self.sent_date(data)
     message.accounting_year = message.sent.year
     for attachment in data['Attachments']:
         Attachment.create(message=message,
                           organization_id=message.organization_id,
                           filename=attachment["Name"],
                           mimetype=attachment["ContentType"],
                           size=attachment["ContentLength"],
                           data=base64.b64decode(attachment["Content"]))
     return Response('ok')
コード例 #21
0
def export_events_ics():
    import sw.allotmentclub.browser.calendar
    parser = gocept.logging.ArgumentParser(
        description="Export events in ics format.")
    parser.add_argument('-c',
                        '--config',
                        default='portal.ini',
                        help='Specify the config file. (default: portal.ini)')
    parser.add_argument('-t', '--type', help='The type (Mitglied|Vorstand)')
    options = parser.parse_args()
    assert options.type in ('Mitglied', 'Vorstand')

    queries = {
        'Mitglied': sw.allotmentclub.browser.calendar.MitgliederQuery,
        'Vorstand': sw.allotmentclub.browser.calendar.VorstandQuery
    }

    Application.from_filename(options.config)

    name = ('Mitgliederliste'
            if options.type == 'Mitglied' else 'Vorstandsliste')
    output = f"""\
BEGIN:VCALENDAR
VERSION:2.0
PRODID:VerwaltungLeunaBundalow
X-WR-CALNAME:Leuna-Siedlung {name}
NAME:Leuna-Siedlung Mitgliederliste
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Berlin
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
"""

    db = zope.component.getUtility(risclog.sqlalchemy.interfaces.IDatabase)
    query = queries[options.type](db, User.by_username('system')).select()
    for event in query:
        m = hashlib.md5()
        m.update('-'.join(str(i) for i in event).encode())
        uid = m.hexdigest()
        if event[-2]:
            timestamp = event[4].strftime('%Y%m%dT000000Z')
            start = end = event[4].strftime('%Y%m%d')
            if event[5]:
                end = event[5].strftime('%Y%m%d')
        else:
            timestamp = event[4].strftime('%Y%m%dT%H%M%SZ')
            start = end = event[4].strftime('%Y%m%dT%H%M%S')
            if event[5]:
                end = event[5].strftime('%Y%m%dT%H%M%S')
        output += f"""\
BEGIN:VEVENT
DTSTAMP:{timestamp}
UID:{uid}@roter-see.de
DTSTART;TZID=Europe/Berlin:{start}
DTEND;TZID=Europe/Berlin:{end}
SUMMARY:{event[2]}
LOCATION:{event[3]}
END:VEVENT
"""
    output += "END:VCALENDAR"
    print(output)
コード例 #22
0
def get_user(request):
    user_id = request.authenticated_userid
    if user_id:
        return User.get(user_id)
コード例 #23
0
def test__mail__postmark_inbound_webhook_1(browser):
    """It creates an inbound email for every request."""
    from sw.allotmentclub import Message, User
    user = User.find_or_create(username='******')
    browser.post(
        'http://localhost/mail/postmark_inbound_webhook',
        data={"FromName": "Postmarkapp Support",
              "From": "*****@*****.**",
              "FromFull": {
                  "Email": "*****@*****.**",
                  "Name": "Postmarkapp Support",
                  "MailboxHash": ""
              },
              "To": ("\"Firstname Lastname\" "
                     "<*****@*****.**>"),
              "ToFull": [
                  {
                      "Email": "*****@*****.**",
                      "Name": "Firstname Lastname",
                      "MailboxHash": "SampleHash"
                  }
              ],
              "Cc": ("\"First Cc\" "
                     "<*****@*****.**>, [email protected]>"),
              "CcFull": [
                  {
                      "Email": "*****@*****.**",
                      "Name": "First Cc",
                      "MailboxHash": ""
                  },
                  {
                      "Email": "*****@*****.**",
                      "Name": "",
                      "MailboxHash": ""
                  }
              ],
              "OriginalRecipient": "*****@*****.**",
              "Subject": "Test subject",
              "MessageID": "73e6d360-66eb-11e1-8e72-a8904824019b",
              "ReplyTo": "*****@*****.**",
              "MailboxHash": "SampleHash",
              # "Date": "Fri, 1 Aug 2014 16:45:32 -04:00",
              "Date": "Sat, 19 Aug 2017 19:37:23 +0200 (Mitteleurop?ische",
              "TextBody": "This is a test text body.",
              "HtmlBody": ("<html><body><p>"
                           "This is a test html body."
                           "</p></body></html>"),
              "StrippedTextReply": "This is the reply text",
              "Tag": "TestTag",
              "Headers": [
                  {
                      "Name": "X-Header-Test",
                      "Value": ""
                  },
                  {
                      "Name": "X-Spam-Status",
                      "Value": "No"
                  },
                  {
                      "Name": "X-Spam-Score",
                      "Value": "-0.1"
                  },
                  {
                      "Name": "X-Spam-Tests",
                      "Value": "DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_PASS"
                  }
              ],
              "Attachments": [
                  {
                      "Name": "test.pdf",
                      "Content": MINIMAL_TEST_PDF_CONTENTS,
                      "ContentType": "application/pdf",
                      "ContentLength": 739
                  }
              ]})
    mail = Message.query().one()
    assert '*****@*****.**' == mail.externals[0].email
    assert 'Postmarkapp Support' == mail.externals[0].lastname
    assert [] == mail.members
    assert "Test subject" == mail.subject
    assert user == mail.user
    assert mail.inbound is True
    assert ("<html><body><p>"
            "This is a test html body."
            "</p></body></html>" == mail.body)
    assert 1 == len(mail.attachments)
    assert MINIMAL_TEST_PDF_CONTENTS.encode() == base64.b64encode(
        mail.attachments[0].data)
    assert 'application/pdf' == mail.attachments[0].mimetype
    assert 'test.pdf' == mail.attachments[0].filename
    assert int(mail.attachments[0].size) == len(mail.attachments[0].data)