Blog
Trying Out Shoop eCommerce
Shoop is a new eCommerce platform developed and open sourced by Anders Innovation (https://www.andersinnovations.com/en/). It caught my attention because the company behind it has been some fairly interesting projects and is packed with promising talent. Additionally, it's based on Python and Django - the platforms I've been developing mainly on lately. Shoop is its early stages and beginning of its lifecycle, so it seems to be a bit rough around the edges and the documentation published is not exactly comprehensive. I gave it a test run and here are the notes written during process. Downloading and InstallingThere does not seem to be official releases (or maybe it's their development model) and Shoop is only available via Github (https://github.com/shoopio/shoop). First though, create a virtualenv to accommodate the project and activate it: pormb:Sites por$ virtualenv shooptest New python executable in shooptest/bin/python Installing setuptools, pip...done. pormb:Sites por$ cd shooptest/ pormb:shooptest por$ source bin/activate (shooptest)pormb:shooptest por$ Then clone the repository, and install Shoop and its dependencies. (shooptest)pormb:shooptest por$ git clone https://github.com/shoopio/shoop.git Cloning into 'shoop'... remote: Counting objects: 1752, done. remote: Total 1752 (delta 0), reused 0 (delta 0), pack-reused 1752 Receiving objects: 100% (1752/1752), 2.43 MiB | 1.53 MiB/s, done. Resolving deltas: 100% (705/705), done. Checking connectivity... done. (shooptest)pormb:shooptest por$ pip install shoop/ Unpacking ./shoop ... ... *** bunch of lines snipped *** ... Successfully installed Babel Django django-bootstrap3 django-countries django-enumfields django-filer django-jinja django-mptt django-parler django-polymorphic django-registration-redux django-timezone-field djangorestframework factory-boy fake-factory jsonfield Markdown pytz requests six shoop enum34 easy-thumbnails Unidecode jinja2 pillow markupsafe Cleaning up... (shooptest)pormb:shooptest por$ Ok! Now we have Shoop installed. The official documentation (at the time of writing) states that "After this, you can begin setting up a Django project using whichever standards you fancy." To me, based on that, it wasn't at all clear on how to proceed. :-) Setting Up the ProjectWithout the help of further instructions, I went on the only way I know - by starting a new Django project with django-admin. (shooptest)pormb:shooptest por$ django-admin startproject shooptest (shooptest)pormb:shooptest por$ cd shooptest/ Now that the project is ready, our freshly installed Shoop needs to be incorporated into it somehow. Documentations mentions modules shoop.core, shoop.front, and shoop.admin. Shoop.core must be a basic requirement for both modules, and in order for the front to make any sense, I'd imagine Shoop needs to be configured, products established etc. So shoop.admin needs to be configured first. So I fired PyCharm (by far the best Python IDE I've tried, check it out https://www.jetbrains.com/pycharm/) and went on to set up the project. Basic configurationAs with all Django projects, external modules need to be included in INSTALLED_APPS setting. So went to add modules mentioned earlier in shooptest/settings.py: # Application definition Now, if you try to migrate the project, an error is displayed: (shooptest)pormb:shooptest por$ python manage.py migrate Traceback (most recent call last): File "manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line utility.execute() File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/django/core/management/__init__.py", line 312, in execute django.setup() File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/django/__init__.py", line 18, in setup apps.populate(settings.INSTALLED_APPS) File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate app_config = AppConfig.create(entry) File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/django/apps/config.py", line 141, in create return cls(app_name, app_module) File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/shoop/apps/__init__.py", line 113, in __init__ self._check_required_installed_apps() File "/Users/por/Sites/shooptest/lib/python2.7/site-packages/shoop/apps/__init__.py", line 141, in _check_required_installed_apps raise ImproperlyConfigured("%s requires the following INSTALLED_APPS: %s" % (self.name, information)) django.core.exceptions.ImproperlyConfigured: shoop.core requires the following INSTALLED_APPS: easy_thumbnails (required), filer (required) (shooptest)pormb:shooptest por$ Aha! shoop.core requires two additional modules: easy_thumbnails and filer. Let's add them to the installed modules in shooptest/settings.py. In the example below I've also added bootstrap3, which is required by shoop.admin. So instead of looking again at an error like the one above, add it as well. INSTALLED_APPS = ( Now that all the required modules are included we should be ready migrate and browse the admin site? Right? Not quite, few things are still missing as indicated by the error. (shooptest)pormb:shooptest por$ python manage.py migrate Traceback (most recent call last): ... django.core.exceptions.ImproperlyConfigured: The DjangoTemplates engine was encountered in your template configuration before Django-Jinja. This configuration will not work correctly with Shoop. (shooptest)pormb:shooptest por$ This is something that bit me. Django-Jinja must be added into TEMPLATES in shooptest/settings.py, and DjangoTemplates must be kept intact. At first I replaced DjangoTemplates with Django-Jinja, and while testing the admin site, I got errors in taxes. So add Django-Jinja before DjangoTemplates: TEMPLATES = [ Okay, that we've cleared that out of the way, can we migrate to set up the database etc? (shooptest)pormb:shooptest por$ python manage.py migrate Operations to perform: Synchronize unmigrated apps: staticfiles, shoop_admin, messages, bootstrap3 Apply all migrations: filer, shoop, sessions, admin, shoop_front, auth, contenttypes, easy_thumbnails Synchronizing apps without migrations: Creating tables... Running deferred SQL... Installing custom SQL... Running migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying easy_thumbnails.0001_initial... OK Applying easy_thumbnails.0002_thumbnaildimensions... OK Applying filer.0001_initial... OK Applying filer.0002_auto_20150606_2003... OK Applying sessions.0001_initial... OK Applying shoop.0001_initial... OK Applying shoop_front.0001_initial... OK (shooptest)pormb:shooptest por$ It seems so - nice! We should be ready to run the development server - but first, we need the admin user. (shooptest)pormb:shooptest por$ python manage.py createsuperuser Username (leave blank to use 'por'): admin Email address: Password: Password (again): Superuser created successfully. (shooptest)pormb:shooptest por$ python manage.py runserver Performing system checks... System check identified no issues (0 silenced). July 11, 2015 - 19:17:09 Django version 1.8.2, using settings 'shooptest.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. Okay, the server is running, but we still need to configure URL routing in order to reach Shoop admin UI. Open up urls.py and add the route for shoop-admin. Please note the required namespace as well. from django.conf.urls import include, url Now Django should be able to find Shoop's admin UI. Browse to http://127.0.0.1:8000/shoop-admin/ and voilá! You should be greeted by Shoop's login Window. Nice! Final wordsShoop seems to contain a bunch of (undocumented) additional modules. They bring additional options into admin UI. Play around with them and what they do. # Application definition |
How to change DHCP provided DNS servers on a Huawei B593s-22
I my previous post Getting SSH access on a Huawei B593s-22 I went on a quest to change the DHCP provided DNS servers on my Huawei B593s-22. Getting SSH access to poke around the filesystem came about a bit tricky, so I figured it merits it's own post. Once I gained root access on the box, I went on to look on how to change the DNS servers. There are several places I looked into and things I tried - which I don't bother you with. With root FTP explained in the previous post, download and edit /app/curcfg.xml. It's the base that's used to create /var/dhcp/dhcps/config upon each boot. DNS servers can be found at Xpath: /InternetGatewayayDevice/LANDevice/LANDeviceInstance/LANHostConfigManagement/@DNSServers i.e. $ xmllint --xpath '/InternetGatewayDeviceConfig/InternetGatewayDevice/LANDevice/LANDeviceInstance/LANHostConfigManagement/@DNSServers' curcfg.xml; echo "" DNSServers="8.8.8.8,8.8.4.4" |
Getting SSH access on a Huawei B593s-22
I have Huawei's B593s-22 4G router as the main connection at home. It's quite neat device, and if 4G connectivity is available, fast too. This morning I wanted to browse Amazon.co.uk on my iPhone (which is connected to WLAN provided by B593s-22), but got a DNS query failure notification. Strange - it's somewhat unlikely that Amazon would have that kind of problems during the christmas sale, so I decided to drop WLAN and try plain cellular (and thus drop the Huawei from the equation). Amazon.co.uk was working fine - a bit of a WTF moment. What exactly does B593s-22 do on my DNS queries for Amazon? Which DNS servers does it use?! We'll, as it seems, it's not that easy. DHCP clients get B593s-22's IP as the DNS server and It's not possible to see or choose which DNS servers B593s-22 uses or gives to DHCP clients from the web user interface. In order to gain further insight, I would need SSH access on the box. Unfortunately the web interface admin password did not work. After Googling around I came across this site which mentions a USB/FTP hack. The instructions are for B593s-12, and the -22 has been changed significantly, so the instructions won't work. Huawei's track record in security is terrible, so I figured it should still be easy to gain access. So I went ahead and connected a FAT-32 formatted 16 GB USB stick in the device and went on to enable the FTP interface: Then went on to add a user: Bummer - according to instructions on above site I would need to type ../../ into the path input box to gain access to the root filesystem. Huawei's engineers have put their best into prevent tampering the box and have changed the input box to a Select button which enables the users to choose from existing folders on the USB stick. Damn.... Well - as mentioned earlier - Huawei's track record in security is shit, so I figured that it's quite possible that the checks and limitations are only client side, and I would only need to get past them. After looking into and fiddling with the source code of the page and various Javascript files it includes, I figured that simple DOM manipulation could be the method. Essentially - I would need to include ../../ in the selection list presented by the Select button. i.e. This can be achieved easily in Google Chrome by just right-clicking an element (i.e. .Spotlight-V100) and choosing Inspect Element. Chrome spits out the source of the page which you can edit to your liking. The edits I made were: Time to test... I went on and FTP'd onto the box. pormb:Downloads por$ ftp 10.254.212.1 Connected to 10.254.212.1. 220 bftpd %v at 10.254.212.1 ready. Name (10.254.212.1:por): ftp 331 Password please. Password: 230 User logged in. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 229 Entering extended passive mode (|||50544|) 150 BINARY data connection established. drwxrwx--x 1 0 0 4096 Nov 28 17:53 app lrwxrwxrwx 1 0 0 14 Jan 01 1970 bin -> system/atp/bin drwxrwx--- 2 1000 2001 0 Jan 01 1970 cache dr-x------ 2 0 0 0 Jan 01 1970 config drwxrwxrwx 1 0 0 4096 Dec 18 2013 cpedata drwxrwx--x 1 1000 1000 4096 Jan 01 2013 data -rw-r--r-- 1 0 0 118 Jan 01 1970 default.prop drwxr-xr-x 10 0 0 0 Dec 13 10:16 dev lrwxrwxrwx 1 0 0 15 Jan 01 1970 etc -> /system/atp/etc -rw-rw-rw- 1 0 0 0 Jan 01 2013 hsvelog.txt lrwxrwxrwx 1 0 0 12 Jan 01 1970 html -> cpedata/html -rwxr-x--- 1 0 0 94168 Jan 01 1970 init -rwxr-x--- 1 0 0 1677 Jan 01 1970 init.goldfish.rc -rwxr-x--- 1 0 0 15298 Jan 01 1970 init.rc lrwxrwxrwx 1 0 0 14 Jan 01 1970 lib -> system/atp/lib drwxr-xr-x 2 0 0 0 Jan 01 1970 media drwxr-xr-x 4 0 0 0 Dec 13 10:16 mnt drwxr-xr-x 1 0 0 4096 Jan 01 1970 online dr-xr-xr-x 123 0 0 0 Jan 01 1970 proc drwx------ 2 0 0 0 Dec 18 2013 root drwxr-x--- 2 0 0 0 Jan 01 1970 sbin drwxr-xr-x 12 0 0 0 Jan 01 1970 sys drwxrwxrwx 1 0 0 4096 Dec 18 2013 system drwxr-xr-x 6 0 0 0 Jan 01 2013 tmp drwxr-xr-x 2 0 0 0 Jan 01 1970 tts -rw-r--r-- 1 0 0 0 Jan 01 1970 ueventd.goldfish.rc -rw-r--r-- 1 0 0 3764 Jan 01 1970 ueventd.rc lrwxrwxrwx 1 0 0 14 Jan 01 1970 usr -> system/atp/usr drwxr-xr-x 25 0 0 0 Dec 13 11:17 var lrwxrwxrwx 1 0 0 15 Jan 01 1970 xbin -> system/atp/sbin 226 Directory list has been submitted. ftp> Nice, Huawei. Your security record still is shit. From either here or here I had already learnt that the plain text SSH passwords can be found in /var/sshusers.cfg. I went on to download it and yes, there it was! pormb:~ por$ ssh admin@10.254.212.1 admin@10.254.212.1's password: ------------------------------- -----Welcome to ATP Cli------ ------------------------------- ATP>shell BusyBox vv1.9.1 (2013-12-18 15:31:27 CST) built-in shell (ash) Enter 'help' for a list of built-in commands. # Now I have an SSH shell, but I've still to solve the DNS issue... |
Import Passwords from Passpack to F-Secure Key
I've been a long time user of Passpack. After F-Secure released it's Key password manager (http://www.f-secure.com/en/web/home_global/key) I decided to give it a shot, and found it very appealing due to it's simplicity. And after using it for a while I decided give up Passpack - there was a problem though... F-Secure Key did not support import of CSV or such formats. Fortunately, it supports few other formats, so it is possible to convert from Passpack's CSV to one of the other formats. Below is the script I wrote for the task. Basically, you can format just about any export format to the simple CSV format:
Usage: fskey.py input.csv > output.xml And output.xml is ready to be imported in F-Secure Key. #!/usr/bin/python # -*- coding: utf-8 -*- import lxml.etree import sys import csv if len( sys.argv ) != 2: print '%s csv.txt' % sys.argv[0] sys.exit() def utf8_csv_reader( utf8_data, dialect = csv.excel, **kwargs ): csv_reader = csv.reader( utf8_data, dialect = dialect, **kwargs ) for row in csv_reader: yield [ unicode( cell, 'utf-8' ) for cell in row ] root = lxml.etree.Element( 'passwordsafe' ) with open( sys.argv[1], 'rb' ) as csvfile: lines = utf8_csv_reader( csvfile, delimiter = ',', quotechar = '"' ) for line in lines: ( name, uid, pwd, link, tags, note, email ) = line notes = [] if len( email ) > 0: notes.append( 'Email: %s' % ( email ) ) if len( note ) > 0: notes.append( note ) entry = lxml.etree.SubElement( root, 'entry' ) lxml.etree.SubElement( entry, 'title' ).text = name lxml.etree.SubElement( entry, 'url' ).text = link lxml.etree.SubElement( entry, 'username' ).text = uid lxml.etree.SubElement( entry, 'password' ).text = pwd lxml.etree.SubElement( entry, 'notes' ).text = '\n\n'.join( notes ) print lxml.etree.tostring( root, pretty_print = True, xml_declaration = True, encoding = 'utf-8' )
|
Apache LDAP Authentication
A simple, concise description of Apache configuration with LDAP authentication. I wish I had found this two hours ago: |
Logging on a Juniper SRX
How to do simple logging on an SRX? set system syslog archive size 100k set system syslog archive files 3 set system syslog file blocked-traffic any any set system syslog file blocked-traffic match RT_FLOW_SESSION_DENY set system syslog file accepted-traffic any any set system syslog file accepted-traffic match RT_FLOW_SESSION_CREATE Then on your policy rule have for example set security policies from-zone trust to-zone untrust policy then-log-and-drop match source-address any set security policies from-zone trust to-zone untrust policy then-log-and-drop match destination-address any set security policies from-zone trust to-zone untrust policy then-log-and-drop match application any set security policies from-zone trust to-zone untrust policy then-log-and-drop then reject set security policies from-zone trust to-zone untrust policy then-log-and-drop then log session-init And with show log blocked-traffic show log accepted-traffic see what's happening. Alternatively, monitor the packet flow on the device: set security flow traceoptions file flow-trace set security flow traceoptions file size 1m set security flow traceoptions file files 2 set security flow traceoptions file world-readable set security flow traceoptions flag basic-datapath set security flow traceoptions packet-filter filter1 destination-prefix 1.2.3.4/32 And with show log flow-trace examine the flow. For reference, here's an image that describes the processing order of different modules within JunOS. Original available in here: http://kb.juniper.net/InfoCenter/index?page=content&id=KB16110. Happy troubleshooting! |
Cisco Stencils for Evolus Pencil
I'm very accustomed of using Cisco Network Stencils (available in here) in MS Office Visio at work. On my personal computer I'm unfortunately limited to free software, such as Evolus Pencil. Pencil, on the other hand, is missing stencils for network diagramming which makes it pretty much useless for network diagrams. To fix this, I've converted the Cisco Stencil package to the format Evolus' Pencil uses. File available below. I do not own any rights to the images - they belong to Cisco Systems. |
Disable GIMP Splash Screen on OS X
GIMP's finally got an OS X native build - yay! There's one thing, that I found very annoying. Each time you start the program, the splash screen is displayed on top of the window stack covering other windows. And it's not possible to Option-Tab it away. There's help though. It's possible to disable the splash screen entirely, by editing the startup script. So navigate to /Applications/GIMP.app/Contents/MacOS and edit file called GIMP. At he bottom you'll see something like this: if [ "x$GTK_DEBUG_SHELL" != "x" ]; then exec bash else $EXEC "$bundle_contents/MacOS/$name-bin" fi Add --no-splash on the second last line: if [ "x$GTK_DEBUG_SHELL" != "x" ]; then exec bash else $EXEC "$bundle_contents/MacOS/$name-bin" --no-splash fi |
Drupal Multisite Performance
A while back I heard that Drupal performs badly on multi site (around 50 or so sites) environments. It made my wonder what exactly makes the difference. Basically, it's just a LAMP stack, and 50 site folders shouldn't make a significant difference. I decided to test it out... for the test I created a fresh Drupal 6.15 installation, and generated 1, 20, 50 and 100 sites within it. Each site containing 200 nodes (with paragraphs from H.G. Wells' War of the Worlds as content, thanks to Project Gutenberg). Each installation was hammered with 50 concurrent users each requesting 5 pages (with Siege, available in here). And the result? As expected... With 1-50 sites the performance has no difference what so ever. Most of the time is spent waiting for the database, so caching database objects is the easiest and probably most effective way to improve performance. After 50 sites my humble test machine runs out of memory so the ball is dropped pretty much immediately. The scripts I used for testing and generating are attached below. |
Drupal XMLRPC: Create Nodes with Python
As a part of another project, I needed to create a lot (hundreds) of nodes in Python programmatically. The key to this is Service API, available in here: http://drupal.org/node/109782. Links on the page led me to this tutorial which uses a cookie aware transport available from here. To my disappointment, the CookieTransport code doesn't work on Python 2.7. I got an error about missing getreply() method. Inspection of the code made me wonder if there would be a better way to implement the same functionality, but without copying large chunks of the parent class code to the subclass. A solution which appeared to me as rather non-oop... Below you'll find the code which works nicely on Python 2.7. Otherwise the linked tutorial is very useful. Another thing to note is that when using Services API, I needed to grant access to Services API for Anonymous user. API itself requires authentication regardless. #!/usr/bin/python import xmlrpclib class CookieTransport( xmlrpclib.Transport ): def __init__( self ): xmlrpclib.Transport.__init__( self ) self.cookies = {} def set_cookie( self, key, value ): self.cookies[key] = value def unset_cookie( self, key ): if self.cookies.haskey( key ): del self.cookies[key] def get_cookies( self ): cookies = [] for key in self.cookies.keys(): cookies += [ '%s=%s' % ( key, self.cookies[key] ) ] return cookies def get_http_cookies( self ): cookies = self.get_cookies() return '; '.join( cookies ) if len( cookies ) > 0 else None def send_host( self, connection, host ): cookies = self.get_http_cookies() if cookies != None: connection.putheader( 'Cookie', cookies ) return xmlrpclib.Transport.send_host( self, connection, host ) def parse_response( self, response ): for header in response.getheaders(): if header[0] == 'set-cookie': cookie = header[1].split( ';' )[0].strip() key, value = cookie.split( '=' ) self.cookies[key] = value return xmlrpclib.Transport.parse_response( self, response ) |
1-10 of 13