def topology_access_check(request, callee, action, **kwargs): """Checks that the user can access the functions they're trying to, and if they can calls callee. There are two valid authentication methods - django logihn, as normally used for the website, and a cryptographic token supplied in the HTTP GET, as used for clack. @param request An HTTP request @param callee Gives the Callable to call @param action One of "add", "change", "use", "delete", describing the permissions needed @param tid The ID of the topology in question; not used for action = "add" @exception ValueError If an action is unrecognised @exception KeyError If an option is missing @return HttpResponse""" def denied(): """Generate an error message and redirect if we try do something to a topology we're not allowed to""" messages.error(request, "Either this topology doesn't exist or you don't " "have permission to %s it." % action) return HttpResponseRedirect('/login/') def denied_add(): """Generate an error message and redirect if we try to create a topology and are not allowed to""" messages.error(request, "You don't have permission to create topologies.") return HttpResponseRedirect('/login/') # If we're trying to add a template, don't need to get the template itself if action == "add": if permissions.allowed_topology_access_create(request.user): return callee(request) else: return denied_add() else: # Try getting the template - if it doesn't exist, show the same message # as for permission denied. If we don't have a "tid" argument, django # will show an internal error, which is what we want. tid = int(kwargs["tid"]) kwargs["tid"] = tid try : topo = db.Topology.objects.get(pk=tid) except db.Topology.DoesNotExist: return denied() if action == "use": # See if there is an HTTP GET token - if there is, try to use the token # method for authentication try: token = request.GET["token"] except KeyError: pass else: # See if the token is valid user = crypto.validate_token(token) if user != None and permissions.allowed_topology_access_use(user, topo): request.user = user return callee(request, topo=topo, **kwargs) if permissions.allowed_topology_access_use(request.user, topo): return callee(request, topo=topo, **kwargs) else: return denied() elif action == "change": if permissions.allowed_topology_access_change(request.user, topo): return callee(request, topo=topo, **kwargs) else: return denied() elif action == "delete": if permissions.allowed_topology_access_delete(request.user, topo): return callee(request, topo=topo, **kwargs) else: return denied() else: raise ValueError("Unknown action: %s" % options["action"])
def group_topology_create(request, group, **kwargs): """Create topologies for a group, with each user in the group becoming the owner of one topology. @param request An HttpRequest @param group The group to add the topologies for""" tn = "vns/group_topology_create.html" # Check we're allowed to create topologies if not permissions.allowed_topology_access_create(request.user): messages.info("Please login as a user who is permitted to create topologies.") return HttpResponseRedirect('/login/?next=/topology/create/') # Import a function to create the form CreateTopologyForm = make_ctform(request.user) if request.method == "POST": form = CreateTopologyForm(request.POST) if form.is_valid(): template_id = form.cleaned_data['template'] ipblock_id = form.cleaned_data['ipblock'] num_to_create = form.cleaned_data['num_to_create'] ip = form.cleaned_data['ip_subnet'] mask = form.cleaned_data['ip_subnet_mask'] # Do lots of permissions and existence checks - need a topology # template and IP block try: template = db.TopologyTemplate.objects.get(pk=template_id) except db.TopologyTemplate.DoesNotExist: messages.error(request, "No such template") return direct_to_template(request, tn, { 'form': form, 'group': group}) try: ipblock = db.IPBlock.objects.get(pk=ipblock_id) except db.IPBlock.DoesNotExist: messages.error(request, "No such IP block") return direct_to_template(request, tn, { 'form': form, 'group': group}) if not permissions.allowed_topologytemplate_access_use(request.user, template): messages.error(request, "You cannot create topologies from this template") return direct_to_template(request, tn, { 'form': form, 'group': group}) if not permissions.allowed_ipblock_access_use(request.user, ipblock): messages.error(request, "You cannot create topologies in this IP block") return direct_to_template(request, tn, { 'form': form, 'group': group}) if num_to_create > 5: messages.error(request, "You cannot create >5 topologies / user at once") return direct_to_template(request, tn, { 'form': form, 'group': group}) # Get a list of users try: users = User.objects.filter(vns_groups=group) except User.DoesNotExist: messages.error("No users in this group to create topologies for") return HttpResponseRedirect("/") # Tell the DBService module to use this thread for accessing the DB DBService.thread = threading.current_thread() # Otherwise, we're good to actually create the topologies, subject # to permissions checks on each user. # These variables track the number with permissions errors, the # number successfully created and the number rwith other errors # to report to the user. num_perms = 0 num_created = 0 num_errs = 0 for u in users: # Check we have permission to change this user if not permissions.allowed_user_access_change(request.user, u): num_perms += 1 continue # Make a list of source IP filters if ip != None and mask != None: src_filters = [(ip, mask)] else: src_filters = [] # Create the topology for _ in xrange(0,num_to_create): err,_,_,_ = instantiate_template(org=u.get_profile().org, owner=u, template=template, ip_block_from=ipblock, src_filters=src_filters, temporary=False, use_recent_alloc_logic=False, public=False, use_first_available=True) # Update the numbers with/without errors if err is not None: num_errs += 1 else: num_created += 1 # Report to the user topology_create_message(request, num_errs, num_perms, num_created) return HttpResponseRedirect('/org/%s/%s/' % (group.org.name, group.name)) else: # The form is not valid messages.error(request, "Invalid form") return direct_to_template(request, tn, {'form':form, 'group':group}) else: # request.method != 'POST' # Need to give them a form but do nothing else return direct_to_template(request, tn, {'form':CreateTopologyForm(), 'group':group})
def topology_create(request): # make sure the user is logged in if not permissions.allowed_topology_access_create(request.user): messages.info("Please login as a user who is permitted to create topologies.") return HttpResponseRedirect('/login/?next=/topology/create/') tn = 'vns/topology_create.html' CTForm = make_ctform(request.user) if request.method == 'POST': form = CTForm(request.POST) if form.is_valid(): template_id = form.cleaned_data['template'] ipblock_id = form.cleaned_data['ipblock'] num_to_create = form.cleaned_data['num_to_create'] try: template = db.TopologyTemplate.objects.get(pk=template_id) except db.TopologyTemplate.DoesNotExist: messages.error(request, "No such template") return direct_to_template(request, tn, { 'form': form }) try: ipblock = db.IPBlock.objects.get(pk=ipblock_id) except db.IPBlock.DoesNotExist: messages.error(request, "No such IP block") return direct_to_template(request, tn, { 'form': form }) if not permissions.allowed_topologytemplate_access_use(request.user, template): messages.error(request, "You cannot create topologies from this template") return direct_to_template(request, tn, { 'form': form }) if not permissions.allowed_ipblock_access_use(request.user, ipblock): messages.error(request, "You cannot create topologies in this IP block") return direct_to_template(request, tn, { 'form': form }) if num_to_create > 30: messages.error(request, "You cannot create >30 topologies at once") return direct_to_template(request, tn, { 'form': form }) # TODO: should validate that request.user can use the requested # template and IP block # Tell the DBService that we want to make the database calls from this thread DBService.thread = threading.current_thread() # try to create the topologies src_filters = [] for i in range(num_to_create): err, _, _, _ = instantiate_template(request.user.get_profile().org, request.user, template, ipblock, src_filters, temporary=False, use_recent_alloc_logic=False, public=False, use_first_available=True) if err is not None: messages.error(request, "Successfully allocated %d '%s' topologies from %s. Failed to make the other request topologies: %s." % (i, template.name, ipblock, err)) return direct_to_template(request, tn) messages.success(request, "Successfully allocated %d '%s' topologies from %s." % (num_to_create, template.name, ipblock)) return direct_to_template(request, tn) else: form = CTForm() return direct_to_template(request, tn, { 'form': form })
def can_create_topology(self): return permissions.allowed_topology_access_create(self.user)