def mutate(self, info, category, title, points, description, flag, hosted, ports, image_name=None, upload=None): user = info.context.user # Validate user is admin validate_user_is_admin(user) # sanitize all the input fields validate_flag(flag) validate_flag_unique(flag) validate_points(points) validate_title(title) validate_description(description) validate_category_exists(category) if image_name: validate_imageName(image_name) if ports: validate_ports(ports) # if path_prefix: # validate_pathPrefix(path_prefix) # validate_pathPrefix_unique(path_prefix) # parse dockerfile for list of ports if upload: try: ports = list() for line in upload: line = line.decode('utf-8') start = 'EXPOSE ' if (start in line): possible_port = (line[line.find(start)+len(start):]) ports.append(possible_port.split()) # flatten list flattened_ports = list( set([val for sublist in ports for val in sublist])) print(flattened_ports) except Exception as e: raise Exception('Error parsing uploaded Dockerfile: ', e) challenge_category = Category.objects.get(id=category) # Save the challenge flag to the database challenge = Challenge(category=challenge_category, title=title, description=description, flag=flag, points=points, hosted=hosted, imageName=image_name, ports=ports) challenge.save() # set var for pathPrefix and tag path_tag = str(challenge.id) challenge.pathPrefix = path_tag if upload: image_name = path_tag + ':latest' # build image build = d.buildImage(fileobj=upload.file, tag=path_tag) # delete already saved challenge if build fails if not build: chall_id = challenge.id try: challenge.delete() except: # raise exception if unable to delete already saved challenge requiring manual intervention raise Exception( 'Unable to delete challenge ID: %i. Manual deletion necessary.' % (chall_id)) raise Exception( 'Unable to build image. Reverted challenge creation.') challenge.upload = upload challenge.imageName = image_name challenge.save() # Push the realtime data to rethinkdb connection = r.connect(host=RDB_HOST, port=RDB_PORT) try: r.db(CTF_DB).table('challenges').insert({'sid': challenge.id, 'category': challenge.category.id, 'title': title, 'points': points, 'description': description, 'hosted': hosted, 'imageName': image_name, 'ports': ports, 'pathPrefix': path_tag, 'created': format(challenge.created, 'U')}).run(connection) except RqlRuntimeError as e: raise Exception( 'Error adding challenge to realtime database: %s' % (e)) finally: connection.close() return AddChallenge(status='Challenge Created')