Commits

Owen Nelson committed f67e441

seperating the package source from the rest of the stuff

  • Participants
  • Parent commits 8816d5d

Comments (0)

Files changed (22)

 ^.project$
 ^.pydevproject$
 ^.settings/
+^build/
+^dist/
 ^test_proj/local_settings.py$
 ^test_proj/uploads
 .*\.db$
+Copyright (c) 2011 Owen Nelson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+include LICENSE

File docs/index.rst

 django-trawler
 ==============
-
 Introduction
 ------------
-
 Trawler is a django app designed to help train and track **phishing** awareness.
 When used as directed, you can launch your own *phaux-phising* campaign and track
 the members of your organization that actually *follow the link* or load the 
 
 Installation
 ------------
-
 If you're familiar with django apps, this process will be fairly natural.
 I'm not planning on pushing this project to PyPI until the code has been 
 **tested** thoroughly **in production**, so for now installation should be handled
 
 From the repo
 ^^^^^^^^^^^^^
-
 This section expects you to have a basic familiarity with `pip <http://www.pip-installer.org/>`_, 
 `virtualenv <http://www.virtualenv.org/>`_, and optionally 
 `virtualenvwrapper <http://www.doughellmann.com/projects/virtualenvwrapper/>`_ (recommended).
 
+.. Hiding the below block until the project has been sent to PyPI.
+   From PyPI
+   ^^^^^^^^^
+   Once this package has been pushed out to PyPI, simply naming the package will 
+   do the trick:  
+
+   ``easy_install django-trawler`` or ``pip install django-trawler``
 
 Using ``pip``, you can install directly from the repo.
 
 Here's an example using pip+virtualenv+virtualenvwrapper: ::
 
 	owen@enso:~/workspace$ mkvirtualenv foo
-	
 	... snip ...
-	
 	(foo)owen@enso:~/workspace$ hg clone https://bitbucket.org/onelson/django-trawler my_trawler
-	
 	... snip ...
-	
 	(foo)owen@enso:~/workspace$ cd my_trawler/
 	(foo)owen@enso:~/workspace/my_trawler$ ls
 	docs  pylintrc  setup.py  test_proj  trawler
-	
 	(foo)owen@enso:~/workspace/my_trawler$ python setup.py develop
 	running develop
 	running egg_info
-	
 	... snip ...
-	
 	Finished processing dependencies for django-trawler==0.1
+	(foo)owen@enso:~/workspace/my_trawler$
 
 It's worth noting that while working with the selected virtualenv, ``python`` is
 the executable based in the virtualenv, so when you run ``python setup.py develop``
 
 Once this link is created, you can run ``python manage.py [...]`` in the ``test_proj``
 directory and that project should be able to *find* the trawler code in the ``sys.path``.
- 
 
-.. Hiding the below block until the project has been sent to PyPI.
-
-.. From PyPI
-   ^^^^^^^^^
-
-   Once this package has been pushed out to PyPI, simply naming the package will 
-   do the trick:  
-
-   ``easy_install django-trawler`` or ``pip install django-trawler``
+Post-Install Configurations
+---------------------------
+Django itself is listed as a dependency in trawler's setup.py, so regardless of 
+the installation source or method, you should have everything you need in place 
+to fire up the app. All that is required of you is the customization of a few 
+key settings in the ``test_proj/settings.py`` (or your own, if you're deploying 
+**for reals**).
 
 .. toctree::
    :maxdepth: 2
 from setuptools import setup, find_packages
+import sys
+sys.path.insert(0, 'src')
 import trawler
 setup(
     name="django-trawler",
     author="Owen Nelson",
     author_email="onelson@gmail.com",
     license="MIT",
-    description="Django App for running phishing campaings (for staff security awareness training)",
+    description="Django App for running phishing campaings (for staff security"
+    " awareness training)",
     keywords="phishing",
-    packages=find_packages(),
+    package_dir={'':'src'},
+    packages=find_packages('src'),
     setup_requires=('setuptools'),
-    install_requires=('setuptools','django>=1.3'),
+    install_requires=('setuptools', 'django>=1.3'),
 )
 

File src/trawler/__init__.py

+__version__ = '0.1'

File src/trawler/admin.py

+from django.contrib import admin
+
+from trawler.models import Campaign, Target
+
+class TargetInline(admin.TabularInline):
+    model = Target
+
+class CampaignAdmin(admin.ModelAdmin):
+
+    list_display = ['title', 'created', 'dispatched']
+    date_hierarchy = 'created'
+    actions = ['send_test_email', 'launch_campaign']
+
+    inlines = [TargetInline, ]
+
+    def send_test_email(self, request, queryset):
+        [campaign.dispatch(request.user.email) for campaign in queryset]
+        count = queryset.count()
+        stuff = 'email' if count == 1  else 'emails'
+        self.message_user(request, "{0} test {1} sent to "
+                          "{2}".format(count, stuff, request.user.email))
+
+    def launch_campaign(self, request, queryset):
+        [campaign.bulk_dispatch() for campaign in queryset]
+        count = queryset.count()
+        stuff = 'campaign' if count == 1  else 'campaigns'
+        self.message_user(request, "{0} {1} launched. Game on!".format(count,
+                                                                       stuff))
+
+admin.site.register(Campaign, CampaignAdmin)

File src/trawler/models.py

+from django.db import models
+from django.core.mail import EmailMessage, EmailMultiAlternatives
+from datetime import datetime
+
+
+class Campaign(models.Model):
+    title = models.CharField(max_length=45)
+    sender = models.EmailField()
+    subject = models.CharField(max_length=255)
+
+    email_plain = models.TextField()
+    email_html = models.TextField(blank=True)
+    img = models.FileField(upload_to='uploads/%Y/%m/%d', null=True, blank=True)
+
+    created = models.DateTimeField(auto_now_add=True, editable=False)
+    dispatched = models.DateTimeField(null=True, default=None, editable=False)
+
+
+    def __unicode__(self):
+        return self.title
+
+    def bulk_dispatch(self):
+        [self.dispatch(target.email, target.pk) for target in self.targets.all()]
+        self.dispatched = datetime.now()
+        self.save()
+
+    def dispatch(self, recipient, upk=None):
+        text_content = self.email_plain.format(recipient=recipient, upk=upk,
+                                                   campaign=self)
+        if self.email_html:
+            # plain text and html content
+            html_content = self.email_html.format(recipient=recipient, upk=upk,
+                                                  campaign=self)
+            msg = EmailMultiAlternatives(self.subject, text_content,
+                                         self.sender, [recipient])
+            msg.attach_alternative(html_content, "text/html")
+        else:
+            # plain text only
+            msg = EmailMessage(self.subject, text_content, self.sender,
+                               [recipient])
+        msg.send()
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('campaign_detail', (), {'pk': self.pk})
+
+class Target(models.Model):
+    email = models.EmailField()
+    campaign = models.ForeignKey(Campaign, related_name='targets')
+    link_followed = models.BooleanField(default=False, editable=False)
+    image_viewed = models.BooleanField(default=False, editable=False)
+    updated = models.DateTimeField(auto_now=True, editable=False)
+
+    def __unicode__(self):
+        return self.email
+

File src/trawler/templates/404.html

Empty file added.

File src/trawler/templates/500.html

Empty file added.

File src/trawler/templates/trawler/campaign_detail.html

+<!DOCTYPE html>
+<html>
+	
+	<head></head>
+	<style type="text/css">
+		table { border-collapse: collapse; }
+		td, th { 
+			border: solid 1px; 
+			padding: 5px 2em; }
+		td.true { background: #C22; }
+		td.false { background: #2C2; }
+	</style>
+	<body>
+		<table>
+			<tr>
+				<th>who</th>
+				<th>link followed</th>
+				<th>image viewed</th>
+				<th>updated</th>
+			</tr>
+			{% for target in campaign.targets.all %}
+			<tr>
+				<td>{{target.email}}</td>
+				<td class="{{target.link_followed|lower}}">{{target.link_followed}}</td>
+				<td class="{{target.image_viewed|lower}}">{{target.images_viewed}}</td>
+				<td>{{target.updated}}</td>
+			</tr>
+			{% endfor %}
+		</table>		
+	</body>
+</html>

File src/trawler/urls.py

+from django.conf.urls.defaults import patterns, include, url
+from trawler.views import CampaignDetail
+urlpatterns = patterns('',
+    url(r'^l/(?P<target_id>\d)/(.*)$', 'trawler.views.link_hits',
+        name='link_hits'),
+    url(r'^i/(?P<target_id>\d)/(.*)$', 'trawler.views.img_hits',
+        name='img_hits'),
+    url(r'^campaign/(?P<pk>\d)/$',
+        CampaignDetail.as_view(), name='campaign_detail')
+)

File src/trawler/views.py

+from django.http import HttpResponse, Http404
+from django.views.generic.detail import DetailView
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+from trawler.models import Target, Campaign
+import mimetypes
+
+def link_hits(request, target_id):
+    mark = Target.objects.get(pk=target_id)
+    mark.link_followed = True
+    mark.save()
+    raise Http404()
+
+def img_hits(request, target_id):
+    mark = Target.objects.get(pk=target_id)
+    mark.image_viewed = True
+    mark.save()
+    try:
+        img = mark.campaign.img
+        return HttpResponse(open(img.path, 'rb'),
+                            mimetype=mimetypes.guess_type(img.path))
+    except:
+        raise Http404()
+
+class CampaignDetail(DetailView):
+    model = Campaign
+    context_object_name = 'campaign'
+
+    @method_decorator(login_required)
+    def dispatch(self, *args, **kwargs):
+        return super(CampaignDetailView, self).dispatch(*args, **kwargs)

File test_proj/__init__.py

Empty file removed.

File trawler/__init__.py

-__version__ = '0.1'

File trawler/admin.py

-from django.contrib import admin
-
-from trawler.models import Campaign, Target
-
-class TargetInline(admin.TabularInline):
-    model = Target
-
-class CampaignAdmin(admin.ModelAdmin):
-
-    list_display = ['title', 'created', 'dispatched']
-    date_hierarchy = 'created'
-    actions = ['send_test_email', 'launch_campaign']
-
-    inlines = [TargetInline, ]
-
-    def send_test_email(self, request, queryset):
-        [campaign.dispatch(request.user.email) for campaign in queryset]
-        count = queryset.count()
-        stuff = 'email' if count == 1  else 'emails'
-        self.message_user(request, "{0} test {1} sent to "
-                          "{2}".format(count, stuff, request.user.email))
-
-    def launch_campaign(self, request, queryset):
-        [campaign.bulk_dispatch() for campaign in queryset]
-        count = queryset.count()
-        stuff = 'campaign' if count == 1  else 'campaigns'
-        self.message_user(request, "{0} {1} launched. Game on!".format(count,
-                                                                       stuff))
-
-admin.site.register(Campaign, CampaignAdmin)

File trawler/models.py

-from django.db import models
-from django.core.mail import EmailMessage, EmailMultiAlternatives
-from datetime import datetime
-
-
-class Campaign(models.Model):
-    title = models.CharField(max_length=45)
-    sender = models.EmailField()
-    subject = models.CharField(max_length=255)
-
-    email_plain = models.TextField()
-    email_html = models.TextField(blank=True)
-    img = models.FileField(upload_to='uploads/%Y/%m/%d', null=True, blank=True)
-
-    created = models.DateTimeField(auto_now_add=True, editable=False)
-    dispatched = models.DateTimeField(null=True, default=None, editable=False)
-
-
-    def __unicode__(self):
-        return self.title
-
-    def bulk_dispatch(self):
-        [self.dispatch(target.email, target.pk) for target in self.targets.all()]
-        self.dispatched = datetime.now()
-        self.save()
-
-    def dispatch(self, recipient, upk=None):
-        text_content = self.email_plain.format(recipient=recipient, upk=upk,
-                                                   campaign=self)
-        if self.email_html:
-            # plain text and html content
-            html_content = self.email_html.format(recipient=recipient, upk=upk,
-                                                  campaign=self)
-            msg = EmailMultiAlternatives(self.subject, text_content,
-                                         self.sender, [recipient])
-            msg.attach_alternative(html_content, "text/html")
-        else:
-            # plain text only
-            msg = EmailMessage(self.subject, text_content, self.sender,
-                               [recipient])
-        msg.send()
-
-    @models.permalink
-    def get_absolute_url(self):
-        return ('campaign_detail', (), {'pk': self.pk})
-
-class Target(models.Model):
-    email = models.EmailField()
-    campaign = models.ForeignKey(Campaign, related_name='targets')
-    link_followed = models.BooleanField(default=False, editable=False)
-    image_viewed = models.BooleanField(default=False, editable=False)
-    updated = models.DateTimeField(auto_now=True, editable=False)
-
-    def __unicode__(self):
-        return self.email
-

File trawler/templates/404.html

Empty file removed.

File trawler/templates/500.html

Empty file removed.

File trawler/templates/trawler/campaign_detail.html

-<!DOCTYPE html>
-<html>
-	
-	<head></head>
-	<style type="text/css">
-		table { border-collapse: collapse; }
-		td, th { 
-			border: solid 1px; 
-			padding: 5px 2em; }
-		td.true { background: #C22; }
-		td.false { background: #2C2; }
-	</style>
-	<body>
-		<table>
-			<tr>
-				<th>who</th>
-				<th>link followed</th>
-				<th>image viewed</th>
-				<th>updated</th>
-			</tr>
-			{% for target in campaign.targets.all %}
-			<tr>
-				<td>{{target.email}}</td>
-				<td class="{{target.link_followed|lower}}">{{target.link_followed}}</td>
-				<td class="{{target.image_viewed|lower}}">{{target.images_viewed}}</td>
-				<td>{{target.updated}}</td>
-			</tr>
-			{% endfor %}
-		</table>		
-	</body>
-</html>

File trawler/urls.py

-from django.conf.urls.defaults import patterns, include, url
-from trawler.views import CampaignDetail
-urlpatterns = patterns('',
-    url(r'^l/(?P<target_id>\d)/(.*)$', 'trawler.views.link_hits',
-        name='link_hits'),
-    url(r'^i/(?P<target_id>\d)/(.*)$', 'trawler.views.img_hits',
-        name='img_hits'),
-    url(r'^campaign/(?P<pk>\d)/$',
-        CampaignDetail.as_view(), name='campaign_detail')
-)

File trawler/views.py

-from django.http import HttpResponse, Http404
-from django.views.generic.detail import DetailView
-from django.contrib.auth.decorators import login_required
-from django.utils.decorators import method_decorator
-from trawler.models import Target, Campaign
-import mimetypes
-
-def link_hits(request, target_id):
-    mark = Target.objects.get(pk=target_id)
-    mark.link_followed = True
-    mark.save()
-    raise Http404()
-
-def img_hits(request, target_id):
-    mark = Target.objects.get(pk=target_id)
-    mark.image_viewed = True
-    mark.save()
-    try:
-        img = mark.campaign.img
-        return HttpResponse(open(img.path, 'rb'),
-                            mimetype=mimetypes.guess_type(img.path))
-    except:
-        raise Http404()
-
-class CampaignDetail(DetailView):
-    model = Campaign
-    context_object_name = 'campaign'
-
-    @method_decorator(login_required)
-    def dispatch(self, *args, **kwargs):
-        return super(CampaignDetailView, self).dispatch(*args, **kwargs)