Exemplo n.º 1
0
def on_user_create(new_user):
    
    print "on_user_create"
    permissions = new_user.merged_permissions()
    
    # If the user has "FTP client" rights then create an FTP user
    if "ftp_client" in permissions["proftpd"]:
        username, password = new_user.username, new_user.password
        
        proftpd = Proftpd(new_user)
        
        # We don't like spaces in directory names, so replace them with underscores
        homedir = os.path.join(proftpd.config["DefaultRoot"][0], \
                               username.replace(" ", "_"))
        
        # Create FTP user
        ftp_user = Users.objects.create(username=username,
                                        password=crypt.crypt(password, password),
                                        homedir=homedir)
        
        # Creating a home directory
        if not (os.path.exists(homedir) and os.path.isdir(homedir)):
            os.mkdir(homedir)
        
        # Changing the owner
        try:
            os.chown(homedir, PROFTPD_UID, PROFTPD_GID)
        except OSError, (errno, sterror):
            log(3, "proftpd_app - event:on_user_create", "OS error(%s): %s" % (errno, sterror))
        
        # Creating user groups
        for group in new_user.groups.all():
            Groups.objects.create(groupname=group.name, username=username)
        
        proftpd.update_config()
Exemplo n.º 2
0
def on_user_change(user, data):
    username = user.username
    new_password = data.get('password', None)
    ftp_user, created = Users.objects.get_or_create(username=username)
    proftpd = Proftpd()
    if created:
        ftp_user.homedir = os.path.join(proftpd.config["DefaultRoot"][0], \
                                        username.replace(" ", "_"))
        
        try:
            os.mkdir(ftp_user.homedir)
            os.chown(ftp_user.homedir, PROFTPD_UID, PROFTPD_GID)                # Changing owner
        except OSError:
            log(5, "proftpd_app - event:on_user_change", "Failed to create directory or alter its owner")
    
    # Changing users's password
    if new_password:
        ftp_user.password = crypt.crypt(new_password, new_password)
    
    ftp_user.save()
    
    # Updating directory permissions
    if "ftp_client" in user.merged_permissions()["proftpd"]:
        proftpd.update_config()
    
    # Recreating groups
    ftp_groups = Groups.objects.filter(username=username)
    ftp_groups.delete()
    
    for group in user.groups.all():
        Groups.objects.create(groupname=group.name, username=username)
    
    return 1
Exemplo n.º 3
0
 def max_permissions(self, map=None):
     if not map:
         map = Permission.map
     
     if isinstance(map, dict):
         rslt = {}
         for m in map:
             rslt[m] = self.max_permissions(map[m])
             
         return rslt
     elif hasattr(map, "cls") and map.cls == "form":
         if isinstance(map.value, dict):
             first_value = map.value[map.value.keys()[0]]
             if first_value.type == "radio":
                 best_value = first_value
                 for key in map.value:
                     if best_value < map.value[key]:
                         best_value = map.value[key]
                 
                 return {best_value.name: self.max_permissions(best_value)}
             else:
                 return self.max_permissions(map.value)
         else:
             return ""
     elif isinstance(map, (basestring, unicode)):
         return map
     
     log(7, "admin_app - Permission class", "max_permissions: Unrecogniseable type")
     return None
Exemplo n.º 4
0
def radio(*args):
    rate = 0
    radios = S()
    args = list(args)
    while len(args):
        radio_title, radio_value = args.pop(0), args.pop(0)
        if isinstance(radio_value, (basestring, unicode)):
            radios[radio_value] = _Radio(radio_value, radio_title, radio_value, rate)
        elif isinstance(radio_value, dict):
            value_key = radio_value.keys()[0]
            if not isinstance(radio_value[value_key], (tuple, list)):
                radio_value[value_key] = (radio_value[value_key],)
            
            tmp_radios = S()
            for radio in radio_value[value_key]:
                if isinstance(radio, dict):
                    key = radio.keys()[0]
                    tmp_radios.update(radio)
                else:
                    log(5, "admin_app - radio function", "Type mismatch.")
            
            radios[value_key] = _Radio(value_key, radio_title, tmp_radios, rate)
        else:
            log(5, "admin_app - radio function", "Unknown radio_value type.")
        
        rate += 1
    
    return radios
Exemplo n.º 5
0
 def __dissect(self, perm1, perm2, map=None):
     if isinstance(perm1, dict) and isinstance(perm2, dict):
         perm = {}
         for p in perm1:
             if not p in perm2:
                 perm[p] = deepcopy(perm1[p])
             else:
                 pp = self.__dissect(perm1[p], perm2[p], map[p])
                 if pp:
                     perm[p] = pp
         
         return perm
     elif perm1 and not perm2:
         return perm1
     else:
         if isinstance(perm1, (unicode, basestring)) and isinstance(perm2, dict):
             perm2_str = perm2.keys()[0]
             perm1_str = perm1
         elif isinstance(perm1, dict) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1.keys()[0]
         elif isinstance(perm1, (unicode, basestring)) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1
         else:
             log(7, "admin_app - Permission class", "__dissect: Comparison type mismatch!")
             return None
         
         if perm1_str and perm2_str:
             if map[perm1_str] > map[perm2_str]:
                 return perm1
         else:
             return ""
     
     return None
Exemplo n.º 6
0
 def update_config(self):
     self.config.update(Groups.objects.all().distinct(), Users.objects.all())
     if self.config.save():
         self.reconfig()
         return 1
     else:
         log(8, "ProftpdConfig - config update", "Failed to update config")
         return 0
Exemplo n.º 7
0
 def __render(self, map, min_permission, max_permission, default):
     html = ""
     
     for p in max_permission:
         if p in map:
             if map[p].type == "radio":
                 """
                 We also have to fetch the minimum permission to disable 
                 forms which reprensent even lower permissions. In order to
                 do this, if min_permission contains a non-null dictionary
                 than get its first value.
                 """
                 min_perm = min_permission
                 if min_perm:
                     for map_key in min_permission:
                         min_perm = min_permission[map_key]
                         break
                 
                 """
                 As there should be a default value in a radio button set in
                 any case, check the default and if it's empty set the lowest
                 possible (not disabled) permission from the map as the default
                 """
                 if not default:
                     for map_key in map:
                         if map[map_key] >= min_perm:
                             default[map_key] = map[map_key]
                             break
                 
                 """
                 Now, go through the map and disable all permissions which are
                 lower than the min_permission and hide all which are higher
                 than max_permission.
                 """
                 for map_key in map:
                     if map[map_key] <= max_permission[p]:
                         radio = map[map_key].html(bool(map[map_key] < min_perm), \
                                                   bool(map[map_key].name in default))
                         if map[map_key].stub:
                             html += "<li>%s</li>" % radio
                         else:
                             inner = self.__render(map[map_key], min_permission.get(map_key, {}), self.to_map(self.max_permissions(map[map_key]), map[map_key]), default.get(map_key, {}))
                             html += '<li>%s<ul class="form">%s</ul></li>' % (radio, inner)
                     else:
                         break
             elif map[p].type in ("title", "checkbox"):
                 min_perm = min_permission.get(p, {})
                 def_perm = default.get(p, {})
                 if not map[p].stub:
                     html_form = map[p].html(bool(min_perm), bool(def_perm))
                     a = self.__render(map[p], min_perm, max_permission[p], def_perm)
                     html += '<li>%s<ul class="form">%s</ul></li>' % (html_form, a)
                 else:
                     html += "<li>%s</li>" % map[p].html(bool(min_permission.get(p, {})), bool(default.get(p, {})))
             else:
                 log(7, "admin_app - Permission class", "__render: Unknown type %s" % map[p].type)
     
     return html
Exemplo n.º 8
0
 def update(self):
     serial = self.config[self.zone_name]['SOA']['params']['serial']
     self.config[self.zone_name]['SOA']['params']['serial'] = str(int(serial)+1)
     if self.save():
         render_to_task("rndc reload %s" % self.zone_name)
         return 1
     else:
         log(8, "ZoneConfig - serial update", "Failed to update serial for a zone %s" % self.zone_name)
         return 0
Exemplo n.º 9
0
 def gen_map():
     result = S()
     apps = map(lambda x: x.split(".")[1], filter(lambda x: x.split(".")[0]=="wenix", INSTALLED_APPS))
     for p in apps:
         try:
             perm = __import__("wenix.%s.permissions" % p, globals(), locals(), ['MAP'])
         except ImportError:
             log(3, "<Permission.gen_map>", "Ignoring permissions for '%s'" % p)
         else:
             result.update(perm.MAP)
     
     return result
Exemplo n.º 10
0
def on_user_login(request, user):
    ip_address = request.META["REMOTE_ADDR"]
    user_agent = uainfo(request.META["HTTP_USER_AGENT"])
    try:
        name = "%s %s" % (user_agent["browser"]["name"], user_agent["browser"]["version"])
        distrib = "%s %s" % (user_agent["dist"]["name"], user_agent["dist"]["version"])
        
        obj, created = UserAgent.objects.get_or_create(codename=user_agent["browser"]["name"],
                                                       name=name,
                                                       ip_address=ip_address,
                                                       platform=user_agent["os"]["name"],
                                                       defaults={"distrib":distrib,"count": 0})
        obj.count += 1
        obj.save()
    except:
        log(5,"misc.middleware.Counter", "Error occured while parsing '%s'" % user_agent)
Exemplo n.º 11
0
 def to_dictionary(self, mapped_perm):
     d = {}
     for m in mapped_perm:
         if isinstance(mapped_perm[m], dict):
             d[m] = self.to_dictionary(mapped_perm[m])
         elif hasattr(mapped_perm[m], "cls") and mapped_perm[m].cls == "form":
             if isinstance(mapped_perm[m].value, dict):
                 d[m] = self.to_dictionary(mapped_perm[m].value)
             elif mapped_perm[m].type == "radio":
                 return mapped_perm[m].name
             else:
                 d[m] = ""
         else:
             log(7, "admin_app - Permission class", "to_dictionary: unrecognizeable type: '%s'" % mapped_perm[m])
     
     return d
Exemplo n.º 12
0
 def __cmp(self, perm1, perm2, map):
     in_form = bool(hasattr(perm1, "cls") and hasattr(perm2, "cls"))
     stub = bool(in_form and  perm1.stub and perm2.stub)
     
     if isinstance(perm1, dict) and isinstance(perm2, dict):
         for p in perm2:
             if not p in perm1:
                 return -1
             else:
                 cmp = self.__cmp(perm1[p], perm2[p], map[p])
                 if cmp:
                     return cmp
                 
         for p in perm1:
             if not p in perm2:
                 return 1
     else:
         if isinstance(perm1, (unicode, basestring)) and isinstance(perm2, dict):
             perm2_str = perm2.keys()[0]
             perm1_str = perm1
         elif isinstance(perm1, dict) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1.keys()[0]
         elif isinstance(perm1, (unicode, basestring)) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1
         else:
             # Type mismatch
             log(7, "admin_app - Permission class", "__cmp: comparison type mismatch!")
             return None
         
         if perm1_str and perm2_str:
             if map[perm2_str] > map[perm1_str]:
                 return -1
             elif map[perm2_str] == map[perm1_str]:
                 return 0
             else:
                 return 1
         
     
     return 0
Exemplo n.º 13
0
 def __merge(self, perm1, perm2, map):
     if isinstance(perm1, dict) and isinstance(perm2, dict):
         for p in perm2:
             if not p in perm1:
                 perm1[p] = deepcopy(perm2[p])
             else:
                 perm1[p] = self.__merge(perm1[p], perm2[p], map[p])
             
         return perm1
     elif perm2 and not perm1:
         return perm1
     else:
         if isinstance(perm1, (unicode, basestring)) and isinstance(perm2, dict):
             perm2_str = perm2.keys()[0]
             perm1_str = perm1
         elif isinstance(perm1, dict) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1.keys()[0]
         elif isinstance(perm1, (unicode, basestring)) and isinstance(perm2, (unicode, basestring)):
             perm2_str = perm2
             perm1_str = perm1
         else:
             # Type mismatch
             log(7, "admin_app - Permission class", "__merge: Comparison type mismatch!")
             return None
         
         
         if perm1_str and perm2_str:
             if map[perm2_str] > map[perm1_str]:
                 return perm2_str
             else:
                 return perm1_str
         elif perm2_str and not perm1_str:
             return perm2
         else:
             return perm1
     
     # Type mismatch
     return None
Exemplo n.º 14
0
def checkbox(*args):
    checkboxes = S()
    args = list(args)
    while len(args):
        title, value = args.pop(0), args.pop(0)
        if isinstance(value, dict):
            value_key = value.keys()[0]
            if not isinstance(value[value_key], (tuple, list)):
                value[value_key] = (value[value_key],)
            
            tmp_chkboxes = S()
            for d in value[value_key]:
                if isinstance(d, dict):
                    tmp_chkboxes.update(d)
                else:
                    log(5, "admin_app - checkbox function", "Type mismatch.")
            
            checkboxes[value_key] = _Checkbox(value_key, title, tmp_chkboxes)
        elif isinstance(value, (basestring, unicode)):
            checkboxes[value] = _Checkbox(value, title, value)
        else:
            log(5, "admin_app - checkbox function", "Unrecognised value type")
    
    return checkboxes
Exemplo n.º 15
0
def on_user_delete(user, victim):
    mode = user.merged_permissions()['accounts']['actions']['mode']
    username = victim.username
    groups = Groups.objects.filter(username=username)
    groups.delete()
    
    try:
        ftp_user = Users.objects.get(username=username)
    except:
        log(1, "proftpd_app - event:on_user_delete", "No user with username '%s' has been found" % username)
        return 1
    
    homedir = ftp_user.homedir
    
    # Gonna make changes to the config
    proftpd = Proftpd(user)
    config = proftpd.config
    
    # Deleting the user from permission instances in the config
    permissions = victim.merged_permissions()
    if "ftp_client" in permissions["proftpd"]:
        users = Users.objects.exclude(username='******')
        homedirs = []
        [homedirs.append(user.homedir) for user in users]
        config.remove(["<Directory>", homedirs, "<Limit>", "*"], "AllowUser", [username])
    
    # Deleting <Directory> instance from config
    path = proftpd.path()
    for p in path.ftp_dir_generator("/"+username, childs_only=True):
        config.drop(["<Directory>"], [p])
        if p in FTP_DB:
            del FTP_DB[FTP_DB[p]]
    
    # Deleting the user's instances from DB permissions
    for dir in FTP_DB:
        dir_perm = dict(FTP_DB[dir])
        if "user" in dir_perm and username in dir_perm["user"]:
            del dir_perm["user"][username]
            FTP_DB[dir] = dir_perm
    
    FTP_DB.save()
    
    # Deleting the directory itself
    try:
        shutil.rmtree(homedir)
    except:
        log(3, "proftpd_app - event:on_user_delete", "Failed to delete user's directory")
    
    if ftp_user:
        ftp_user.delete()
    
    # Reconfiguring...
    if not proftpd.update_config():
        log(3, "proftpd_app - event:on_user_delete", "Failed to delete 'Directory' instance from the configuration file")
    
    return 1
Exemplo n.º 16
0
 def __process(self, name, apps, *args):
     rslts = {}
     for app in apps:
         try:
             APP = __import__("wenix.%s.event" % app, globals(), locals(), [name])
         except ImportError, e:
             log(1, "custom - user:__process", "Event load failure (%s): %s" % (app, e))
         else:
             try:
                 sub = getattr(APP, name)
             except:
                 log(0, "custom - group:__process", "Application '%s' has no event '%s'" % (app, name))
             else:
                 rslt = sub(*args)
                 if not rslt:
                     log(6, "custom - group:__process", "Unsuccessful result returned from '%s' application" % app)
                 else:
                     rslts[app] = rslt
Exemplo n.º 17
0
def title(*args):
    titles = S()
    args = list(args)
    while len(args):
        title_key, title_value = args.pop(0), args.pop(0)
        if isinstance(title_value, dict):
            if not len(title_value) == 1:
                log(3, "admin_app - title function", "Dictionary length is more than one")
                break
            
            child_key = title_value.keys()[0]
            if isinstance(title_value[child_key], dict):
                child_value = title_value[child_key]
            else:
                log(3, "admin_app - title function", "Unknown title type")
            
            titles[child_key] = _Title(child_key, title_key, child_value)
        else:
            log(5, "admin_app - title function", "Unknown title's value type")
            break
    
    return titles
Exemplo n.º 18
0
def delete(request, perm):
    user = request.user
    id = request.GET.get("id", None)
    object = request.GET.get("object", None)
    confirm_request = request.GET.get("cfm_req", None)
    mode = user.merged_permissions()['accounts']['actions']['mode']
    
    if not (id and object):
        log(5, "accounts_app - account delete", "Void request")
        return HttpResponseBadRequest()
    
    if not object in ("user", "group"):
        log(5, "accounts_app - account delete", "Unrecognised object type '%s'" % object)
        return HttpResponseBadRequest()
    
    if object == "user":
        # User deletion
        victim = WenixUser.objects.get(pk=id)
        if victim.is_superuser:
            log(5, "accounts_app - account delete", "An attempt to delete a superuser by '%s'" % request.user.username)
            return HttpResponse(json.dumps({"ok": 0, "error": _("Superuser cannot be deleted")}), mimetype="application/json")
        
        if victim == user:
            log(5, "accounts_app - account delete", "An attempt of self-deletion by '%s'" % request.user.username)
            return HttpResponse(json.dumps({"ok": 0, "error": _("You cannot delete yourself")}), mimetype="application/json")
        
        # We are just going to ask for confirmation
        # qstn - an array with questions and some information about what is going to be deleted
        # qstn is then concatenated into one string
        if confirm_request:
            qstn = []
            info = WenixUser.objects.info(user, victim).values()
            if info:
                info[0] = " - %s" % info[0]
                qstn.append(" - \n".join(info))
            
            qstn.append(_('Are you sure you want to delete the user %(username)s? All user-related information, including files and statistics, will be lost.') % {'username': victim.username})
            return HttpResponse(json.dumps({"confirm": "\n".join(qstn)}), mimetype="application/json")
        
        WenixUser.objects.on_delete(user, victim)
        #cache.delete(CACHE_KEY_USERPERM % victim.username)
        
        if mode == 'group':
            for group in victim.groups.all():
                if group in user.groups:
                    victim.groups.remove(group)
            
            if victim.groups.count() == 0:
                victim.delete()
            
        elif mode == 'global':
            victim.delete()
        
    else: # object == "group":
        # Group deletion
        if mode != "global":
            log(5, "accounts_app - account delete", "An attempt to delete a group without global piviliges by '%s'" % user.username)
            return HttpResponseForbidden()
        
        # In a global mode        
        # Fetching all users in the group
        group = WenixGroup.objects.get(pk=id)
        group_users = WenixUser.objects.filter(groups__name=group.name)
        
        # We are just going to ask for confirmation
        if confirm_request:
            # Finding out users to be deleted
            qstn = []
            usernames = []
            for u in group_users:
                if u.groups.count() == 1:
                    usernames.append(u.username)
            
            if usernames:
                users = ", ".join(usernames)
                qstn.append(_("These users are going to be deleted: %(users)s. ") % {'users': users})
            
            info = WenixGroup.objects.info(user, group).values()
            if info:
                info[0] = " - %s" % info[0]
                qstn.append("\n - ".join(info))
            
            qstn.append(_("Are you sure you want to delete the group %(groupname)s?") % {'groupname': group.name})
            
            return HttpResponse(json.dumps({"confirm": "\n".join(qstn)}), mimetype="application/json")
        
        # Informing external modules
        WenixGroup.objects.on_delete(user, group)
        
        # Deleting the group
        for u in group_users:
            if u.groups.count() == 1:
                WenixUser.objects.on_delete(user, u)
                u.delete()
            else:
                u.groups.remove(group)
                #cache.delete(CACHE_KEY_UGRPERM % u.username)
                #cache.delete(CACHE_KEY_USERPERM % u.username)
                
        group.delete()
        
    return HttpResponse(json.dumps({"ok": 1}), mimetype="application/json")
Exemplo n.º 19
0
def manage(request, mode, action):
    data_str = request.POST.get("data", None)
    formset_id = request.COOKIES.get("formset_id", None)
    instance_id = request.POST.get("id",  request.GET.get("id", None))
    data = None
    
    # If in the "edit" mode, account_obj contains either a user or a group object
    # Otherwise the object is None
    account_obj = None
    """
    If data is send, write this data in cache and follow the following steps
    accordingly. Otherwise, if it's a step back return the cached data. In any
    other case it should be the first request in a formset, so return an empty
    form.
    """
    if data_str:
        # The user is submitting the form. Trying to deserialize data first.
        try:
            data = json.loads(data_str)
        except: # Damn... returng a bad request error
            log(6, "accounts_app - account add", "Failed to serialize data string: %s" % data_str)
            return HttpResponseBadRequest()
    
    # Let's dig out the previously recorded data from the cache.
    formset = cache.get(formset_id)
    
    # If the request uses POST method, apperently the user is submiting the form
    if request.method == "POST":
        if formset:
            step = formset["step"]
            object = formset["object"]
            
            # Fetching an object from the DB
            if instance_id and action == "edit":
                if object == "user":
                    class_obj = WenixUser
                else:
                    class_obj = WenixGroup
                
                account_obj = class_obj.objects.get(pk=instance_id)
            
            if data:
                # Get the form and check wether the submitted data valid or not.
                form = get_form(object.title(), action, step)(data)
                if not form.is_valid():
                    print data
                    print form
                    return HttpResponse(json.dumps({"ok": 0,"errors": get_errors(form, data)}),
                                        mimetype="application/json")
                
                # Update formset. All data in the following lines could be reached
                # only with the formset.
                formset["data"].update(data)
                
                """
                If it's the last step in a formset we don't need to return the next
                step, but rather we return the result of the user/group creation.
                """
                if object == "user" and step == 3:
                    u_perm_obj = Permission(formset["data"]["permissions"])
                    perm_obj = Permission(request.user.merged_permissions())
                    groups = WenixGroup.objects.in_bulk(formset["data"]["groups"]).values()
                    
                    g_perm_obj = Permission()
                    for group in groups:
                        g_perm_obj.merge(group.permissions)
                    
                    if u_perm_obj >= g_perm_obj and u_perm_obj <= perm_obj:
                        """
                        Priviliges check has passed. We have nothing to do but to
                        create or change the user.
                        We don't want redundancy, therefore the common attributes
                        will be fetched here.
                        """
                        # User permissions first
                        permissions = u_perm_obj.dissect(g_perm_obj.permissions)
                        if action == "add":
                            new_user = WenixUser.objects.create(username=formset["data"]["username"])
                            
                            # Saving general information about the user
                            for key in ("first_name", "last_name", "email", "permissions"):
                                setattr(new_user, key, formset["data"][key])
                            
                            # Changing the user's membership
                            new_user.groups = groups
                            
                            # We need to store a clean user password in order for
                            # other modules to be aware of it
                            new_user.password = formset["data"]["password"]
                            
                            # Invoking a method to notify all modules about the new user
                            WenixUser.objects.on_create(new_user)
                            
                            # Setting crypted password and saving the user
                            new_user.set_password(formset["data"]['password'])
                            new_user.save()
                            
                            message = _("A new user '%(username)s' has been created") % {"username": new_user.username}
                        else: # action == "edit"
                            account_obj.save()
                            
                            # Saving general information about the user
                            for key in ("first_name", "last_name", "email", "permissions"):
                                setattr(account_obj, key, formset["data"][key])
                            
                            # Resetting the user's password if needed
                            if formset["data"]['password']:
                                account_obj.set_password(formset["data"]['password'])
                            
                            # Changing the user's membership
                            account_obj.groups = groups
                            account_obj.save()
                            
                            # Invoking a method to notify all modules about the change
                            WenixUser.objects.on_edit(account_obj, formset["data"])
                            
                            message = _("The user '%(username)s' has been changed") % {"username": account_obj.username}
                            
                        response = HttpResponse(json.dumps({"ok": 1,"message": message}))
                        response.delete_cookie("formset_id")
                        return response
                    else:
                        """
                        It turns out as if the user created another user with higher
                        priviliges. That breaks the rules, therefore access should be
                        denied.
                        """
                        log(5, "accounts_app - account add", "Permission denied for user '%s' creating another user" % request.user.username)
                        return HttpResponse(json.dumps({"ok": 1, "message": _("Access denied")}))
                
                elif object == "group" and step == 2:
                    g_perm_obj = Permission(formset["data"]["permissions"])
                    perm_obj = Permission(request.user.merged_permissions())
                    
                    if g_perm_obj <= perm_obj:
                        
                        # Fetching users to be included in the group
                        users = WenixUser.objects.in_bulk(formset["data"]["users"] or []).values()
                        
                        """
                        Priviliges check has passed. We have nothing to do but to
                        create or change the group.
                        """
                        if action == "add":
                            # We are going to create a new group.
                            group = WenixGroup.objects.create(name=formset["data"]["name"],
                                                              permissions=g_perm_obj.permissions)
                            
                            # The new members of the group should have their priviliges updated
                            [user.groups.add(group) for user in users]
                            WenixGroup.objects.on_create(group)
                            message = _("A new group '%(name)s' has been created") % {"name": formset["data"]["name"]}
                        else: # action == "edit"
                            # We are going to change a group.
                            group = account_obj
                            
                            # Reseting users's permissions so they can form again
                            # At the same time if a user was in the MultipleChoice
                            # field remove his membership from the group
                            choice_ids = dict(id_and_name_to_dict(request.user, mode, "user")).keys()
                            old_group_users = WenixUser.objects.filter(groups__name=group.name)
                            for u in old_group_users:
                                #cache.delete(CACHE_KEY_UGRPERM % u.username)
                                #cache.delete(CACHE_KEY_USERPERM % u.username)
                                if str(u.id) in choice_ids:
                                    u.groups.remove(group)
                            
                            # Contructing a new dictionary with old_dat to pass with "on_edit" method
                            old_data = {"permissions": group.permissions,
                                        "users": old_group_users}
                            
                            group.permissions = g_perm_obj.permissions
                            group.save()
                            
                            # We're going to add users to the group
                            for user in users:
                                user.groups.add(group)
                                #if not user in old_group_users:
                                #    cache.delete(CACHE_KEY_UGRPERM % user.username)
                                #    cache.delete(CACHE_KEY_USERPERM % user.username)
                            
                            # On edit method has three arguments: user, object_being_changed and new_data
                            WenixGroup.objects.on_edit(request.user, group, old_data)
                            message = _("The priviliges for the group '%(name)s' have been saved") % {"name": group.name}
                        
                        response = HttpResponse(json.dumps({"ok": 1,"message": message}))
                        response.delete_cookie("formset_id")
                        return response
                    else:
                        """
                        It turns out as if the user created another group with higher
                        priviliges. That breaks the rules, therefore access should be
                        denied.
                        """
                        log(6, "accounts_app - account add", "Permission denied for user '%s' creating another group" % request.user.username)
                        return HttpResponse(json.dumps({"ok": 1,"message": _("Access denied")}))
                
                formset["step"] += 1
            else:
                if formset["step"] > 1:
                    formset["step"] -= 1
                else:
                    formset["step"] = 1
            
            step = formset["step"]
            form = get_form(object.title(), action, step)
            
            # Generating the next form according to the step
            if object == "user":
                if step == 1:
                    new_form = form(initial=formset["data"])
                elif step == 2:
                    """
                    We need to initialize group list here. At the same time we can't
                    list groups the user is not a memeber of if she's in the "group"
                    mode. That's why we use "id_and_name_to_dict" function to generate
                    the list.
                    """
                    new_form = form(initial=formset['data'])
                    new_form["groups"].field.choices = id_and_name_to_dict(request.user, mode, "group")
                elif step == 3:
                    # Generating permissions
                    groups = WenixGroup.objects.in_bulk(data["groups"])
                    perm_obj = Permission(request.user.merged_permissions())
                    g_perm_obj = Permission()
                    for g in groups:
                        g_perm_obj.merge(groups[g].permissions)
                    
                    if action == "add":
                        new_form = {"permissions": perm_obj.render(g_perm_obj.permissions)}
                    else: # action == "edit"
                        u_perm_obj = Permission(account_obj.permissions)
                        u_perm_obj.merge(g_perm_obj.permissions)
                        new_form = {"permissions": perm_obj.render(g_perm_obj.permissions, u_perm_obj.permissions)}
                else:
                    # Unrecognised step
                    log(6, "accounts_app - account add", "Unknown step: %s" % step)
                    return HttpResponseBadRequest()
            
            elif object == "group":
                if step == 1:
                    new_form = form(initial=formset["data"])
                    new_form["users"].field.choices = id_and_name_to_dict(request.user, mode, "user")
                elif step == 2:
                    # Generating permissions
                    perm_obj = Permission(request.user.merged_permissions())
                    
                    if action == "add":
                        new_form = {"permissions": perm_obj.render()}
                    else: # action == "edit"
                        g_perm_obj = Permission(WenixGroup.objects.get(pk=instance_id).permissions)
                        new_form = {"permissions": perm_obj.render({}, g_perm_obj.permissions)}
                else:
                    # Unrecognised step
                    log(6, "accounts_app - account add", "Unknown step: %s" % step)
                    return HttpResponseBadRequest()
                
            template = get_template(TEMPLATE_FORM_PATH % object)
            cache.set(formset_id, formset)
            context = Context({"form": new_form, "step": formset["step"], "action": action, "object": account_obj})
            return HttpResponse(json.dumps({"ok": 1, "html": template.render(context)}),
                                mimetype="application/json")
    
    # No formset is found. Therefore, we conclude this is the first step.
    object = request.POST.get("object", request.GET.get("object", ""))
    if not object in ("user", "group"):
        log(3, "accounts_app - account add", "An alien object type '%s' has been spotted" % object)
        return HttpResponseBadRequest()
    
    # Create a new formset
    cache.delete(formset_id)
    formset_id = gen_formset_id(CACHE_FORMSET[action], object)
    form_obj = get_form(object, action, 1)
    
    if action == "add":
        data = {}
        form = form_obj()
    else: # action == "edit"
        if object == "user":
            account_obj = WenixUser.objects.get(pk=instance_id)
            data = {"groups": map(lambda x: str(int(x)), account_obj.groups.all().values_list("id", flat=True))}
            form = form_obj(instance=account_obj)
        else: # object == "group"
            account_obj = WenixGroup.objects.get(pk=instance_id)
            data = {"users": map(lambda x: str(int(x)), WenixUser.objects.filter(groups__name=account_obj.name).values_list("id", flat=True))}
            form = form_obj(initial=data)
    
    # An ugly way to initialize users list
    if object == "group":
        form["users"].field.choices = id_and_name_to_dict(request.user, mode, "user")
    
    cache.set(formset_id, {"object": object, "step": 1, "data": data})
    response = render_to_response(TEMPLATE_FORM_PATH % object, {"form": form, "step": 1, "action": action, "object": account_obj})
    response.set_cookie("formset_id", formset_id, FORMSET_ID_MAXAGE)
    return response
Exemplo n.º 20
0
def record(request, mode, zone_name, action):
   
    data = json.loads(request.REQUEST.get('data', "{}"))
    
    form = BindForm.get_form(zone_name)
    if form is None:
        # add operation for a slave zone requested
        return HttpResponseBadRequest()
    
    if request.method == 'GET':
        # requesting the form
        if action == "add":
            return render_to_response("bind/add_form_rr_%s.django.html" % form.TYPE,
                                     {"form": form(), "zone_name": zone_name})
        elif action == "edit":
            # requesting the form
            record_name = request.GET.get('rrkey', None)
            rrtype = request.GET.get('rrtype', None)
            
            bind_daemon = Bind()
            zone_config = bind_daemon.zone_config(zone_name)
            records = zone_config.config.names[record_name].records(rrtype).get_items()
            
            return render_to_response("bind/edit_form_rr.django.html",
                                     {
                                        "records": records,
                                        "type": rrtype,
                                        "record": record_name,
                                        "zone_name": zone_name})
        else:
            if action != "delete":
                # delete actions are GET requests
                return HttpResponseBadRequest()
        
    if form.TYPE == BindForm.ZONE_STRAIGHT or form.TYPE == BindForm.ZONE_REVERSE:
        if action == "add":
            data["zone_name"] = zone_name
            
            # submitting the form
            form = form(data)
            if not form.is_valid():
                return HttpResponse(json.dumps({"ok": 0, "errors": get_errors(form, data)}), mimetype="application/json")
            
            bind_daemon = Bind()
            
            # making shortcuts for key data
            rrkey = form.cleaned_data['rrkey']          # name
            rrtype = form.cleaned_data['rrtype']        # type
            rrvalue = form.cleaned_data['rrvalue']      # resolve
            
            zone_config = bind_daemon.zone_config(zone_name)
            zone_config.config.add_name(rrkey)
            zone_config.config.names[rrkey].records(rrtype, create=True).add(str(rrvalue))
            zone_config.config.save(autoserial=True)
            
            # Checking whether we need to create a reversed record for straight A-records
            if data["rrtype"] == "A" and request.POST.get('create_reversed', False):
                reverse_form = BindReverse({"rrvalue": rrkey,
                                            "rrkey": rrvalue,
                                            "zone_name": "in-addr.arpa"})
                if reverse_form.is_valid():
                    rrkey = reverse_form.cleaned_data['rrkey']
                    rrvalue = reverse_form.cleaned_data['rrvalue']
                    rrtype = form.cleaned_data['rrtype']
                    zone_name_reverse = bind_daemon.get_zone_name_by_ip(rrvalue)
                    
                    zone_config = bind_daemon.zone_config(zone_name_reverse)
                    zone_config.config.add_name(rrkey)
                    zone_config.config.names[rrkey].records(rrtypem,create=True).add(str(rrvalue))
                    zone_zonfig.config.save(autoserial=True)
                else:
                    # Automatic PTR writing has failed
                    log(2, "bind_app - record add", \
                    "Failed to write a reverse record. Data are: name='%s',resolve='%s'" % (rrkey, rrvalue))
            
            return HttpResponse(json.dumps({"ok": 1, "errors": ""}), mimetype="application/json")
        
        data["rrkey"] = request.REQUEST.get('rrkey', None)
        data["rrtype"] = request.REQUEST.get('rrtype', None)
            
        if action == "edit":
            _data = {'rrtype': data['rrtype'],
                     'rrkey': data['rrkey'],
                     'zone_name': zone_name}
            
            errors = {}
            clean_data = []
            for rrvalue_key in data:
                re_index = re.search("rrvalue_(\d+)", rrvalue_key)
                if not re_index:
                    continue
                
                index = re_index.group(1)
                _data["rrvalue"] = data[rrvalue_key]
                _data['priority'] = data.get("priority_%s" % index, None)
            
                _form = form(_data)
                if _form.is_valid():
                    clean_data.append(_form.cleaned_data["rrvalue"])
                else:
                    _errors = get_errors(_form, _data)
                    for e in _errors:
                        errors["%s_%s" % (e, index)] = _errors[e]
            
            if errors:
                return HttpResponse(json.dumps({"ok": 0, "errors": errors}), mimetype="application/json")
            
            if len(clean_data) != 0:
                bind_daemon = Bind()
                zone_config = bind_daemon.zone_config(zone_name)
                records = zone_config.config.names[data['rrkey']].records(data['rrtype'])
                for item in records.get_items():
                    records.delete(item)
                
                for rrvalue in clean_data:
                    records.add(str(rrvalue))
                
                zone_config.config.save(autoserial=True)
                error = _("The zone '%(zone_name)s' has been changed") % {"zone_name": zone_name}
                    
                return HttpResponse(json.dumps({"ok": 1, "error": error}),
                                    mimetype="application/json")
            else:
                # data is empty. meaning delete the record
                errors = {"general": _("At least on value is required for the record '%(rrkey)s'") % {"rrkey": data['rrkey']}}
                return HttpResponse(json.dumps({"ok": 0, "errors": errors}),
                                    mimetype="application/json")
        
        if action == "delete":
            
            if request.GET.get("flag", None) == "info":
                msg = _('Are you sure you want to delete the %(type)s-record "%(name)s"?' % {"name": data["rrkey"],"type": data["rrtype"]})
                return HttpResponse(json.dumps({"confirm": msg}), mimetype="application/json")
            
            bind_daemon = Bind()
            zone_config = bind_daemon.zone_config(zone_name)
            names = zone_config.config.get_names()
            if data["rrkey"] in names:
                zone_config.config.delete_name(data["rrkey"])
            
            zone_config.config.save(autoserial=True)
          
            return HttpResponse(json.dumps({"ok": 1,
                                            "error": _("The zone '%(zone_name)s' has been changed") % {"zone_name": zone_name}}),
                                mimetype="application/json")
    elif form.TYPE == BindForm.FORWARD or form.TYPE == BindForm.HINT:
        # submitting the form
        
        if action == "add":
            form = form(data)
            if not form.is_valid():
                return HttpResponse(json.dumps({"ok": 0, "errors": get_errors(form, data)}), mimetype="application/json")
 
            
            # making shortcuts for key data
            ipaddress = form.cleaned_data['ipaddress']
            priority = int(form.cleaned_data['priority'])
            
            bind_daemon = Bind()
            named_zone = bind_daemon.get_zone(zone_name)
            forwarders = named_zone.get("forwarders", SortedDict())
            
            # sorting the forwarders according to the priority
            i = 0
            for forwarder in forwarders:
                i += 1
                forwarders[forwarder] = i
            
            forwarders[ipaddress] = priority - 0.5
            
            new_forwarders = SortedDict(sorted(forwarders.items(), key=lambda x:x[1]))
            
            # transforming to an appropriate format
            for forwarder in new_forwarders:
                new_forwarders[forwarder] = True
            
            named_zone["forwarders"] = new_forwarders
            bind_daemon.set_zone(zone_name, named_zone)
            bind_daemon.config.save()
            return HttpResponse(json.dumps({"ok": 1, "errors": ""}), mimetype="application/json")
        elif action == "type":
            # Changing zone type
            
            bind_daemon = Bind()
            named_zone = bind_daemon.get_zone(zone_name)
            
            if data["zone_type"] == "hint":
                named_zone["type"] = "hint"
                named_zone["file"] = BindConfig.ROOT_ZONE_PATH
                if "forwarders" in named_zone:
                    del named_zone["forwarders"]
                    
                if "forward" in named_zone:
                    del named_zone["forward"]
            elif data["zone_type"] == "forward":
                # type == "forward"
                if "file" in named_zone:
                    del named_zone["file"]
                
                named_zone["type"] = "forward"
                named_zone["forward"] = "only"
                if not "forwarders" in named_zone:
                    named_zone["forwarders"] = {}
            else:
                return HttpResponse(json.dumps({"ok": 1, "errors": _("Not implemented")}), mimetype="application/json")
            
            bind_daemon.set_zone(zone_name, named_zone)
            bind_daemon.config.save()
            return HttpResponse(json.dumps({"ok": 1, "errors": ""}), mimetype="application/json")
        elif action == "delete":
            if request.GET.get("flag", None) == "info":
                msg = _('Are you sure you want to delete the forward server "%(name)s"?' % {"name": request.REQUEST.get("rrkey", "")})
                return HttpResponse(json.dumps({"confirm": msg}), mimetype="application/json")
            
            bind_daemon = Bind()
            named_zone = bind_daemon.get_zone(zone_name)
            forwarders = named_zone.get("forwarders", SortedDict())
            forwarder = request.REQUEST.get('rrkey', None)
            if forwarder in forwarders:
                del forwarders[forwarder]
            
            named_zone["forwarders"] = forwarders
            bind_daemon.set_zone(zone_name, named_zone)
            bind_daemon.config.save()
            
            return HttpResponse(json.dumps({"ok": 1,
                                            "error": _("The zone '%(zone_name)s' has been changed") % {"zone_name": zone_name}}),
                                mimetype="application/json")
    else:
        # unrecognized request
        return HttpResponseBadRequest()

    
    #bind_daemon = Bind()
    #zone_config = bind_daemon.zone_config(zone_name)
    #include_file = bind_daemon.check_includefile(ZONE_INCLUDE_FILE % zone_name)
    
    """
Exemplo n.º 21
0
def ftp_client(request, mode):
    
    path = urllib.url2pathname(request.POST.get("dir", request.GET.get("dir", "/")))
    action = request.POST.get("action", request.GET.get("action", "show"))
    flag = request.POST.get("flag", request.GET.get("flag", None))
    proftpd = Proftpd(request.user)
    ftp_client = proftpd.path(path)
    
    if not ftp_client.path_is_valid():
        return HttpResponseBadRequest()
    
    """
    The user is making a request which need a form to be filled in.
    """
    if request.method == "GET":
        action = request.GET.get("action", "show")
        if action == "mkdir":
            return render_to_response("proftpd/window_mkdir.django.html")
        elif action == "upload":
            return render_to_response("proftpd/window_upload.django.html")
        elif action == "change_permission":
            if request.user.is_superuser:
                users = Users.objects.all()
                groups = unique(Groups.objects.all().values_list("groupname", flat=True))
            else:
                users = ftp_client.ftp_user.peers()
                groups = ftp_client.ftp_user.groups()
            
            permissions = ftp_client.permissions()
            print permissions["all"]
            return render_to_response("proftpd/window_perm_change.django.html",
                                      {"selected_groups": permissions["group"],
                                       "selected_users": permissions["user"],
                                       "default": permissions["all"][""],
                                       "users": users,
                                       "groups": groups})
        else:
            return render_to_response("proftpd/ftp_client.django.html",
                                      {"content": ftp_client.dir()},
                                      context_instance=RequestContext(request))
    else:# request == "POST"
        if action == "show":
            template = get_template("proftpd/browser.django.html")
            context = Context({"content": ftp_client.dir()})
            return HttpResponse(template.render(context), mimetype="text/html")
        elif action == "info":
            template = get_template("proftpd/info_browser.django.html")
            context = Context({"info": ftp_client.info()})
            return HttpResponse(template.render(context), mimetype="text/html")
        elif action == "change_permission":
            # Getting the permissions given according to the following scheme:
            # {"default": perm1, "user": {user1: perm2, user2: perm3}, "group":
            # {group1: perm4}}
            permissions = request.POST.get("permissions", None)
            if permissions:
                try:
                    data = json.loads(permissions)
                except: # Damn... returng an error
                    return HttpResponse(json.dumps({"ok": 0, "msg": _("Error occurred while serializing permissions")}), mimetype="application/json")
                
                # Setting he new permissions
                ftp_client.set_permissions(data)
                # Updating the config
                if not proftpd.update_config():
                    return HttpResponse(json.dumps({"ok": 0, "msg": _("Error occurred while saving the new configuration")}), mimetype="application/json")
                
                if ftp_client.is_dir:
                    msg = _("The directory's permissions have been changed")
                else:
                    msg = _("The file's permissions have been changed")
                
            return HttpResponse(json.dumps({"ok": 1, "msg": msg}), mimetype="application/json")
        elif action == "delete":
            if flag == "info":
                if ftp_client.is_file:
                    msg = _('Are you sure you want to delete the file "%(name)s"?' % {"name": ftp_client.name})
                else:
                    msg = _('Are you sure you want to delete the directory "%(name)s"? The contents of the directory will also be deleted.' % {"name": ftp_client.name})
            
                return HttpResponse(json.dumps({"confirm": msg}), mimetype="application/json")
            else:
                return HttpResponse(json.dumps(ftp_client.delete()), mimetype="application/json")
        elif action == "mkdir":
            name = request.POST.get("name", "New Folder")
            return HttpResponse(json.dumps(ftp_client.mkdir(name)), mimetype="application/json")
        elif action == "upload":
            response = ftp_client.upload(request.FILES['file'], \
                                         request.META['REMOTE_ADDR'])
            return HttpResponse(response, mimetype='text/html')
        elif action == "download":
            if ftp_client.has_perm("READ", ftp_client.path) and ftp_client.is_file:
                return HttpResponse(json.dumps({"ok": 1, "redir": FTP_FILES_URL % ftp_client.download(request.META['REMOTE_ADDR'])}), mimetype="application/json")
            else:
                return HttpResponse(json.dumps({"ok": 0, "msg": _("Access denied")}), mimetype="application/json")
        else:
            log(3, "proftpd_app - ftp_client", "Strange action '%s'" % action)
            return HttpResponseBadRequest()
Exemplo n.º 22
0
 def connections(self):
     """
     pid - PID
     un - username
     t_conn - connection time
     actn - action
     loc - location
     host - hostname
     ip_addr - IP address
     """
     
     status = {}
     raw_status = commands.getoutput("ftpwho -v -o oneline -f /var/run/proftpd.scoreboard")
     lines = raw_status.split("\n")
     re_srv_status = re.search("(standalone|inetd).+?\[(\d+)\].*up\s+for\s+(.*)", lines.pop(0))
     if re_srv_status:
         status["server"] = {"mode": re_srv_status.group(1),
                             "pid": re_srv_status.group(2),
                             "uptime": re_srv_status.group(3)}
     else:
         status["server"] = {"mode": "unknown","pid": "unknown","uptime": "unknown"}
     
     total = lines and re.search("(\d+)\s+users", lines.pop()) or []
     if total:
         status["total"] = total.group(1)
     else:
         status["total"] = "0"
     
     status["users"] = {}
     for line in lines:
         for re_t in [self.re_idle, self.re_auth, self.re_actn]:
             if re_t.search(line):
                 found = map(lambda x: x.strip(), re_t.match(line).groups())
                 if re_t == self.re_actn:
                     ip_addr = None
                     host = None
                     pid, un, t_conn, actn, loc = found
                 elif re_t == self.re_auth:
                     actn = "AUTH"
                     un = None
                     loc = None
                     pid, t_conn, host, ip_addr = found
                 elif re_t == self.re_idle:
                     #actn = "IDLE"
                     pid, un, t_conn, actn, host, ip_addr, loc = found
                     actn = actn.upper()
             
                 if not un in status["users"]:
                     status["users"][un] = []
                 
                 status["users"][un].append({"action": actn,
                                             "pid": pid,
                                             "conn_time": t_conn,
                                             "hostname": host,
                                             "ip_address": ip_addr,
                                             "location": loc})
                 break
             else:
                 log(8, "Proftpd Daemon - connections", "An ambigious line: %s" % line)
     
     return status
Exemplo n.º 23
0
def statistics(request, mode):
    search = request.GET.get("value", None)
    period_str = request.GET.get("period", request.POST.get("period", None))
    order_by = request.GET.get("order_by", "username")
    username = request.POST.get("username", None)
    
    data = {"mode": mode}
    traffic = Traffic.objects.all()
    
    # Checking if we were given "period" or "search" variables and setting a
    # template accordingly
    if period_str or search:
        template = "proftpd/search.django.html"
    else:
        # Default values
        template = "proftpd/statistics.django.html"
        start, end = map(lambda x: x.strftime("%d.%m.%Y"), (datetime.now()-timedelta(10), datetime.now()))
        period_str = "%s - %s" % (start, end)
        return render_to_response(template, {"period": period_str}, context_instance=RequestContext(request))
        
    if period_str:
        period = []
        date_format = "([\d\.]+)\s*-\s*([\d\.]+)"
        str_dates = re.search(date_format, period_str)
        for str_date in str_dates.groups():
            re_dates = re.search("(\d{1,2})\.(\d{1,2})\.(\d{4})", str_date)
            if not re_dates:
                return HttpResponseBadRequest()
            
            day, month, year = map(lambda x: int(x), re_dates.groups())
            period.append(datetime(year, month, day))
        
        if period[0] == period[1]:
            period[1] += timedelta(hours=23, minutes=59, seconds=59)
    else:
        return HttpResponseBadRequest()
    
    data['statistics'] = []
    if mode == "self":
        users = (request.user, )
    elif mode == "group":
        users = request.user.peers()
    elif mode == "global":
        users = Users.objects.all()
    else:
        log(3, "proftpd_app - statistics", "Strange statistics mode '%s'" % mode)
        return HttpResponseBadRequest()
    
    today = date.today()
    
    if username:
        template = "proftpd/statistics_detail.django.html"
        cached_traffic = TrafficCache.objects.filter(username=username, date__range=period)
        data["statistics"] = Traffic.objects.filter(transfersize__gt=0, cache__in=cached_traffic).order_by("transferdate")
    else:
        # Checking whether the end period is today. If True we've got to overwrite the cache.
        if datetime.date(period[1]) == today:
            cached_to_delete = TrafficCache.objects.filter(date=today)
            traf = Traffic.objects.filter(transfersize__gt=0, cache__in=cached_to_delete).update(cache=None)
            cached_to_delete.delete()
        
        # Going through the users to calculate the traffic and cache it.
        for user in users:
            if search and not re.search(search, user.username, re.I):
                continue
            else:
                cached_traffic = TrafficCache.objects.filter(username=user.username, date__range=period)
                upload, download = 0, 0
                for cached_traf in cached_traffic:
                    download += int(cached_traf.download)
                    upload += int(cached_traf.upload)
            
            upload_extra, download_extra  = 0, 0
            cached_dates = cached_traffic.values_list("date", flat=True)
            start_datetime = period[0]
            while start_datetime <= period[1]:
                end_datetime = start_datetime + timedelta(hours=23, minutes=59, seconds=59)
                current_date = datetime.date(start_datetime)
                if not current_date in cached_dates:
                    # Go through all the traffic, counting and caching on the way
                    traffic = Traffic.objects.filter(username=user.username, transfersize__gt=0, transferdate__range=(start_datetime, end_datetime))
                    
                    # Caching traffic for future use
                    new_cache = TrafficCache.objects.create(username=user.username, date=current_date)
                    upld, downld  = 0, 0
                    for traf in traffic:
                        if traf.transfertype == "STOR":
                            upld += traf.transfersize
                        elif traf.transfertype == "RETR":
                            downld += traf.transfersize
                            
                        traf.cache = new_cache
                        traf.save()
                    
                    new_cache.upload, new_cache.download = str(upld), str(downld)
                    new_cache.save()
                    
                    upload_extra += upld
                    download_extra += downld
                    
                start_datetime = end_datetime + timedelta(seconds=1)
                
            data['statistics'].append({"username": user.username,
                                       "download": download+download_extra,
                                       "upload": upload+upload_extra})
    
    return render_to_response(template, data, context_instance=RequestContext(request))