예제 #1
0
 def lms_commit(self, request):
     """
     This is how the SCORM player is able to push data back to us when a commit call happens.
     """
     try:
         if request.method != 'POST' or 'auth_token' not in request.POST or 'flashSO' not in request.POST or \
                 'sco_session_id' not in request.POST:
             return HttpResponseBadRequest('Your request must include strings labeled "auth_token", "sco_session_id" and "flashSO".')
         auth_token = Utils.get_auth_token_object(request.POST['auth_token'])
         the_sco_session = Utils.find_by_id(request.POST['sco_session_id'], facade.models.ScoSession)
         the_sco_session.shared_object = request.POST['flashSO']
         shared_object_assignments = the_sco_session.shared_object.split(';')
         # Here we are going to look at the shared object and try to split it out and store it into individual fields in our DB for
         # reporting
         for shared_object_assignment in shared_object_assignments:
             # The last split will be an empty string, so let's make sure we aren't looking at that one
             if len(shared_object_assignment) > 0:
                 try:
                     # Let's get the field name and the value to store in it split by the '=' symbol
                     field_value_pair = shared_object_assignment.split('=')
                     setattr(the_sco_session, field_value_pair[0], field_value_pair[1])
                 except:
                     # If we get an exception here, it is most certainly due to us not having a matching field in our DB, so we'd rather
                     # ignore
                     continue
         the_sco_session.save()
         redirect_url = reverse('db_post_form',
             args=[auth_token.session_id, the_sco_session.id, urllib.quote(the_sco_session.shared_object)])
         return HttpResponse('<meta http-equiv="Refresh" content="0; url=%s">'%(redirect_url))
     except exceptions.AuthTokenExpiredException:
         return HttpResponseNotFound('Your session has expired.  Please log in again!')
    def admin_categories_view(self, auth_token):
        categories = self.get_filtered(auth_token, {}, ['name', 'managers', 'authorized_groups', 'locked'])

        categories = Utils.merge_queries(categories, facade.managers.GroupManager(), auth_token,
            ['name'], 'authorized_groups')

        return Utils.merge_queries(categories, facade.managers.UserManager(), auth_token, 
            ['last_name', 'first_name', 'email'], 'managers')
    def user_videos_view(self, auth_token):
        videos = self.get_filtered(auth_token, {}, ['author',
            'approved_categories', 'create_timestamp', 'description',
            'encoded_videos', 'length', 'name', 'num_views', 'photo_url',
            'src_file_size'])

        videos = Utils.merge_queries(videos, facade.managers.CategoryManager(), auth_token,
            ['name'], 'approved_categories')

        return Utils.merge_queries(videos, facade.managers.EncodedVideoManager(), auth_token, 
            ['bitrate', 'url'], 'encoded_videos')
    def admin_videos_view(self, auth_token):
        videos = self.get_filtered(auth_token, {}, ['author',
            'category_relationships', 'create_timestamp', 'description',
            'encoded_videos', 'length', 'name', 'num_views', 'photo_url',
            'src_file_size'])

        videos = Utils.merge_queries(videos, facade.managers.VideoCategoryManager(), auth_token,
            ['category_name', 'category', 'status'], 'category_relationships')

        return Utils.merge_queries(videos, facade.managers.EncodedVideoManager(), auth_token, 
            ['bitrate', 'http_url', 'url'], 'encoded_videos')
    def admin_categories_view(self, auth_token):
        categories = self.get_filtered(
            auth_token, {},
            ['name', 'managers', 'authorized_groups', 'locked'])

        categories = Utils.merge_queries(categories,
                                         facade.managers.GroupManager(),
                                         auth_token, ['name'],
                                         'authorized_groups')

        return Utils.merge_queries(categories, facade.managers.UserManager(),
                                   auth_token,
                                   ['last_name', 'first_name', 'email'],
                                   'managers')
    def user_videos_view(self, auth_token):
        videos = self.get_filtered(auth_token, {}, [
            'author', 'approved_categories', 'create_timestamp', 'description',
            'encoded_videos', 'length', 'name', 'num_views', 'photo_url',
            'src_file_size'
        ])

        videos = Utils.merge_queries(videos, facade.managers.CategoryManager(),
                                     auth_token, ['name'],
                                     'approved_categories')

        return Utils.merge_queries(videos,
                                   facade.managers.EncodedVideoManager(),
                                   auth_token, ['bitrate', 'url'],
                                   'encoded_videos')
예제 #7
0
    def _run(self, *parameters):
        """
        Execute a call
        
        @param parameters    All of the parameters that were passed
        
        @return               An XML struct indicating status as well
                              as a return value if the invocation was
                              successful.
        """

        start_time = datetime.datetime.utcnow()

        parameters = list(parameters)

        if (len(parameters) > 0 and getargspec(self.method)[0][1] == 'auth_token' and
            isinstance(parameters[0], basestring) and parameters[0]):

            try:
                at = Utils.get_auth_token_object(parameters[0], start_time)
                parameters[0] = at
            except exceptions.PrException, e:
                stop_time = datetime.datetime.utcnow()
                rpc_ret = {}
                rpc_ret['status'] = 'error'
                rpc_ret['error'] = [e.get_error_code(), e.get_error_msg()]
                logger.info(self.format_trace_log_message(start_time,
                    stop_time, rpc_ret, *parameters))
                return rpc_ret
예제 #8
0
 def change_password(self, auth_token, domain, new_password):
     d = self._find_by_id(domain)
     new_hash = Utils._hash(new_password, 'SHA-512')
     self.authorizer.check_update_permissions(
         auth_token, d, {'authentication_password_hash': new_hash})
     d.authentication_password_hash = new_hash
     d.save()
    def admin_videos_view(self, auth_token):
        videos = self.get_filtered(auth_token, {}, [
            'author', 'category_relationships', 'create_timestamp',
            'description', 'encoded_videos', 'length', 'name', 'num_views',
            'photo_url', 'src_file_size'
        ])

        videos = Utils.merge_queries(videos,
                                     facade.managers.VideoCategoryManager(),
                                     auth_token,
                                     ['category_name', 'category', 'status'],
                                     'category_relationships')

        return Utils.merge_queries(videos,
                                   facade.managers.EncodedVideoManager(),
                                   auth_token, ['bitrate', 'http_url', 'url'],
                                   'encoded_videos')
    def upload_video_photo(self, request):
        """Handle Image file uploads for Video thumbnails.

        We are going to look for a Base64 encoded image if a "photo" file
        doesn't exist in request.FILES and add it onto the request object
        before relegating the request object to the superclass

        Since this method calls a celery task that depends on database changes
        made here, we must ensure that the transaction gets commited first.

        :param request:   HttpRequest object from django
        """
        photo_file = request.FILES.get('photo')
        if photo_file is None:
            # upload_video_photo was called, but without the "photo" file.
            # Let's see if we got a base64 string of the "photo"
            photo_b64 = request.POST.get('photo')
            if photo_b64 is None:
                return upload._render_response_bad_request(
                    request,
                    'Request must include photo file or base64 encoded photo parameter'
                )
            try:
                photo_file = SimpleUploadedFile('photo',
                                                base64.b64decode(photo_b64),
                                                'image/png')
                photo_extension = '.png'
            except TypeError:
                # Thrown by b64decode if handed a non base64 string
                return upload._render_response_bad_request(
                    request, 'Could not decode uploaded photo parameter')
        else:
            photo_extension = os.path.splitext(photo_file.name)[1]
        auth_token = request.POST.get('auth_token', None)
        video_id = int(request.POST.get('video_id', None))
        if not (request.method == 'POST' and auth_token and video_id):
            return upload._render_response_bad_request(
                request,
                msg=(
                    "Your request must include exactly one file, the " +
                    "'video_id' of the video you are uploading the photo for, "
                    + "and a variable named 'auth_token'."))
        try:
            video = self._find_by_id(video_id)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(
                auth_token, video, {'photo_url': 'A New Photo!'})
            if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                queue_upload(
                    video, 'photo',
                    'video/%d.thumbnail%s' % (video_id, photo_extension),
                    photo_file)
            return upload._render_response_ok(request,
                                              msg='Image upload successful.')
        except exceptions.PrException, p:
            return upload._render_response_forbidden(request,
                                                     msg=p.get_error_msg())
 def _process_scorm_file(self, auth_token, scorm_file):
     # Make sure that the user is allowed to upload a scorm course
     if not isinstance(auth_token, facade.models.AuthToken):
         auth_token = Utils.get_auth_token_object(auth_token)
     facade.subsystems.Authorizer().check_arbitrary_permissions(auth_token, 'upload_scorm_course')
     scorm_zip_file = zipfile.ZipFile(scorm_file)
     manifest = scorm_zip_file.read('imsmanifest.xml')
     manifest = ElementTree.XML(manifest)
     self._check_manifest(manifest, scorm_zip_file)
     self._create_course(manifest, scorm_zip_file)
 def _process_scorm_file(self, auth_token, scorm_file):
     # Make sure that the user is allowed to upload a scorm course
     if not isinstance(auth_token, facade.models.AuthToken):
         auth_token = Utils.get_auth_token_object(auth_token)
     facade.subsystems.Authorizer().check_arbitrary_permissions(
         auth_token, 'upload_scorm_course')
     scorm_zip_file = zipfile.ZipFile(scorm_file)
     manifest = scorm_zip_file.read('imsmanifest.xml')
     manifest = ElementTree.XML(manifest)
     self._check_manifest(manifest, scorm_zip_file)
     self._create_course(manifest, scorm_zip_file)
 def watcher_report(self,
                    auth_token,
                    videos,
                    start_date=None,
                    end_date=None):
     """
     Returns a list of views of the given videos (optinally filtered by date)
     along with some information about the viewer.
     """
     filters = {'member': {'assignment__task__id': videos}}
     if start_date or end_date:
         filters = [filters]
         if start_date:
             if pr_time.is_iso8601(start_date):
                 start_date = pr_time.iso8601_to_datetime(start_date)
             filters.append(
                 {'greater_than_or_equal': {
                     'date_started': start_date
                 }})
         if end_date:
             if pr_time.is_iso8601(end_date):
                 end_date = pr_time.iso8601_to_datetime(end_date)
             filters.append(
                 {'less_than_or_equal': {
                     'date_started': end_date
                 }})
         filters = {'and': filters}
     views = self.get_filtered(auth_token, filters,
                               ['video', 'date_started', 'user'])
     views = Utils.merge_queries(views, facade.managers.VideoManager(),
                                 auth_token, ['name'], 'video')
     views = Utils.merge_queries(views, facade.managers.UserManager(),
                                 auth_token, [
                                     'first_name', 'last_name', 'email',
                                     'default_username_and_domain'
                                 ], 'user')
     return views
    def upload_video_photo(self, request):
        """Handle Image file uploads for Video thumbnails.

        We are going to look for a Base64 encoded image if a "photo" file
        doesn't exist in request.FILES and add it onto the request object
        before relegating the request object to the superclass

        Since this method calls a celery task that depends on database changes
        made here, we must ensure that the transaction gets commited first.

        :param request:   HttpRequest object from django
        """
        photo_file = request.FILES.get('photo')
        if photo_file is None:
            # upload_video_photo was called, but without the "photo" file.
            # Let's see if we got a base64 string of the "photo"
            photo_b64 = request.POST.get('photo')
            if photo_b64 is None:
                return upload._render_response_bad_request(request,
                    'Request must include photo file or base64 encoded photo parameter')
            try:
                photo_file = SimpleUploadedFile('photo', base64.b64decode(photo_b64), 'image/png')
                photo_extension = '.png'
            except TypeError:
                # Thrown by b64decode if handed a non base64 string
                return upload._render_response_bad_request(request,
                    'Could not decode uploaded photo parameter')
        else:
            photo_extension = os.path.splitext(photo_file.name)[1]
        auth_token = request.POST.get('auth_token', None)
        video_id = int(request.POST.get('video_id', None))
        if not (request.method == 'POST' and auth_token and video_id):
            return upload._render_response_bad_request(request,
                msg=("Your request must include exactly one file, the "+
                    "'video_id' of the video you are uploading the photo for, "+
                    "and a variable named 'auth_token'."))
        try:
            video = self._find_by_id(video_id)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(auth_token,
                video, {'photo_url' : 'A New Photo!'})
            if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                queue_upload(video, 'photo',
                    'video/%d.thumbnail%s' % (video_id, photo_extension),
                    photo_file)
            return upload._render_response_ok(request, msg='Image upload successful.')
        except exceptions.PrException, p:
            return upload._render_response_forbidden(request, msg=p.get_error_msg())
예제 #15
0
    def return_player(self, request, auth_token, sco_id):
        """
        Handle requests by returning the scorm player.
        """
        try:
            the_sco = facade.models.Sco.objects.get(id__exact=sco_id)
            auth_token = Utils.get_auth_token_object(auth_token)
            assignments = facade.models.Assignment.objects.filter(task__id=the_sco.id, user=auth_token.user).order_by('-effective_date_assigned')
            if len(assignments) == 0:
                return HttpResponseNotFound('There is no assignment to view this SCO')
            assignment = assignments[0]
            # Let's try to find an existing sco_session for this SCO and user.  If there isn't one,
            # let's create one.
            potential_sco_sessions = assignment.assignment_attempts.all()
            if len(potential_sco_sessions) == 0:
                the_sco_session = facade.models.ScoSession(assignment=assignment,
                    date_started=datetime.datetime.utcnow())
                the_sco_session.save()
            elif len(potential_sco_sessions) == 1:
                the_sco_session = potential_sco_sessions[0]
            else:
                raise multiple_scorm_sco_sessions_exception
            the_sco_session = the_sco_session.downcast_completely()
            # Form the URL to the HTTP form that will be used to store and POST data to us
            db_form_url = reverse('db_post_form', args=[auth_token.session_id, the_sco_session.id,
                urllib.quote(the_sco_session.shared_object)])

            t = loader.get_template('scorm_player')
            c = Context({
                'user' : auth_token.user,
                'sco_url' : settings.SECURE_MEDIA_URL + the_sco_session.sco.url,
                'auth_token' : auth_token.session_id,
                'db_form_url' : db_form_url,
                'api_adapter_url' : settings.SECURE_MEDIA_URL + 'scorm_player/API_ADAPTER.htm',
                'cmi_db_url' : settings.SECURE_MEDIA_URL + 'scorm_player/CMIDB.html',
            })
            return HttpResponse(t.render(c))
        except facade.models.Sco.DoesNotExist, e:
            return HttpResponseNotFound('The requested Sco does not exist.')
def _get_user_from_token(session_id):
    return Utils.get_auth_token_object(session_id).user
def upload_csv(request, auth_token=None, model_name=None):
    """Handle CSV file uploads

    This method will stick the contents of the uploaded file (of which there
    must be exactly 1) into the database through a csv_data object.  There is
    currently no validation on this end, but Django will raise an exception
    if you try to upload binary data.

    :param request:   HttpRequest object from Django

    """
    log_prefix = u'pr_services.utils.upload.upload_csv(): '

    logging.debug(log_prefix + 'model name [%s]' % str(model_name))

    if request.method == 'GET':
        if auth_token is None:
            return _render_response_forbidden(request,
                msg='Your request must include an auth token in its URL.')
        if model_name is None:
            return _render_response_bad_request(request,
                msg='Your request must include a model name as the last component of its URL.')
        return _render_response(request, 'upload_csv.html',
            {'title': 'CSV File Upload', 'form': CsvUploadForm(),
            'model_name': model_name, 'auth_token': auth_token})

    elif request.method == 'POST':
        if auth_token is None:
            if 'auth_token' in request.POST:
                auth_token = request.POST['auth_token']
            else:
                return _render_response_forbidden(request,
                    msg='Your request must contain a variable named "auth_token".')

        if len(request.FILES) != 1:
            return _render_response_bad_request(request,
                msg='Your request must include exactly one file.')

        if model_name is None:
            if 'model' in request.POST:
                model_name = request.POST['model']
            else:
                return _render_response_bad_request(request,
                    msg='Your request must include a variable named "model", ' + \
                    'specifying which type of model you are uploading.')

    try:
        auth_token = Utils.get_auth_token_object(auth_token)

        # There should only be one file, so this loop exists just because we don't
        # know the file name under which it is indexed.
        c = None
        for filename in request.FILES:
            c = _process_csv_file(auth_token, request.FILES[filename], model_name)

        return _render_response_ok(request, msg=(str(c) if c else None))
    except exceptions.PrException, p:
        log_message = log_prefix + 'PR exception encountered: '
        if request.method == 'POST':
            if 'auth_token' in request.POST:
                log_message += 'auth_token: [%s]' % request.POST['auth_token']
        log_message += u' error code [%s], message [%s], details [%s]' %\
            (unicode(p.get_error_code()), p.get_error_msg(), unicode(p.get_details()))
        logging.info(log_message)

        return _render_response_forbidden(request, msg=p.get_error_msg())
 def change_password(self, auth_token, domain, new_password):
     d = self._find_by_id(domain)
     new_hash = Utils._hash(new_password, 'SHA-512')
     self.authorizer.check_update_permissions(auth_token, d, {'authentication_password_hash' : new_hash})
     d.authentication_password_hash = new_hash
     d.save()
    def vod_admin_groups_view(self, auth_token):
        groups = self.get_filtered(auth_token, {}, ['name', 'categories'])

        return Utils.merge_queries(groups, facade.managers.CategoryManager(),
                                   auth_token, ['name'], 'categories')
 def admin_org_view(self, auth_token):
     orgs = self.get_filtered(auth_token, {}, ['name', 'parent', 'user_org_roles', 'org_email_domains'])
     
     ret = Utils.merge_queries(orgs, facade.managers.OrgEmailDomainManager(), auth_token, ['email_domain', 'effective_role', 'effective_role_name'], 'org_email_domains')
     
     return Utils.merge_queries(ret, facade.managers.UserOrgRoleManager(), auth_token, ['role_name', 'role', 'owner'], 'user_org_roles')
def _get_user_from_token(session_id):
    return Utils.get_auth_token_object(session_id).user
    def admin_org_user_view(self, auth_token, org):
        ret = facade.managers.UserOrgRoleManager().get_filtered(auth_token, {'exact' : {'organization' : org}}, ['role', 'owner'])

        ret = Utils.merge_queries(ret, facade.managers.UserManager(), auth_token, ['first_name', 'last_name', 'email'], 'owner')

        return Utils.merge_queries(ret, facade.managers.OrgRoleManager(), auth_token, ['name'], 'role')
예제 #23
0
def setup(machine):
    group, created = facade.models.Group.objects.get_or_create(
        name="Super Administrators")

    if not machine.options['authz_only']:
        if machine.options.has_key('default_admin_password'):
            password = machine.options['default_admin_password']
        else:
            password = '******'
        salt = machine.user_manager._generate_password_salt()
        password_hash = Utils._hash(password + salt, 'SHA-512')

        user = facade.models.User.objects.create(first_name="admin",
                                                 last_name="user",
                                                 status='active',
                                                 email='*****@*****.**')
        user.groups.add(group)  # no need to save(), it's a ManyToManyField

        local_domain = facade.models.Domain.objects.get(name='local')
        da = facade.models.DomainAffiliation.objects.create(
            user=user,
            username='******',
            domain=local_domain,
            default=True,
            password_hash=password_hash,
            password_salt=salt)

    methods = [
        {
            'name': 'actor_member_of_group',
            'params': {
                'group_id': group.id
            }
        },
        {
            'name': 'refund_does_not_exceed_payment',
            'params': {}
        },
    ]
    arb_perm_list = [
        'check_usernames',
        'change_password_of_other_users',
        'exceed_enrollment_capacity',
        'logging',
        'read_reports',
        'regenerate_payment_confirmations',
        'resend_payment_confirmations',
        'send_email',
        'upload_scorm_course',
    ]
    crud = {
        'Achievement': {
            'c':
            True,
            'r': [
                'component_achievements', 'description', 'name', 'users',
                'yielded_achievements'
            ],
            'u': [
                'component_achievements', 'description', 'name', 'users',
                'yielded_achievements'
            ],
            'd':
            True,
        },
        'AchievementAward': {
            'c': True,
            'r': ['assignment', 'date'],
            'u': ['assignment', 'date'],
            'd': True,
        },
        'Answer': {
            'c':
            True,
            'r': [
                'correct', 'end_exam', 'end_question_pool', 'label',
                'next_question_pool', 'order', 'question', 'text_response',
                'value'
            ],
            'u': [
                'correct', 'end_exam', 'end_question_pool', 'label',
                'next_question_pool', 'order', 'question', 'text_response',
                'value'
            ],
            'd':
            True,
        },
        'Assignment': {
            'c':
            True,
            'r': [
                'task', 'task_content_type', 'user', 'date_started',
                'date_completed', 'due_date', 'prerequisites_met',
                'effective_date_assigned', 'status', 'assignment_attempts'
            ],
            'u': [
                'due_date', 'effective_date_assigned', 'status',
                'date_started', 'date_completed'
            ],
            'd':
            True,
        },
        'AssignmentAttempt': {
            'c': True,
            'r': ['assignment', 'date_started', 'date_completed'],
            'u': ['date_started', 'date_completed'],
            'd': True,
        },
        'Category': {
            'c':
            True,
            'r': [
                'authorized_groups', 'managers', 'name', 'locked', 'videos',
                'approved_videos'
            ],
            'u': ['authorized_groups', 'managers', 'name', 'locked', 'videos'],
            'd':
            True,
        },
        'ConditionTest': {
            'c':
            True,
            'r': [
                'sequence', 'condition_test_collection',
                'match_all_defined_parameters', 'groups', 'credentials',
                'events', 'sessions', 'session_user_role_requirements',
                'start', 'end'
            ],
            'u': [
                'sequence', 'condition_test_collection',
                'match_all_defined_parameters', 'groups', 'credentials',
                'events', 'sessions', 'session_user_role_requirements',
                'start', 'end'
            ],
            'd':
            True,
        },
        'ConditionTestCollection': {
            'c': True,
            'r': ['name', 'condition_tests'],
            'u': ['name'],
            'd': True,
        },
        'CSVData': {
            'c': True,
            'r': [],
            'u': [],
            'd': True,
        },
        'Curriculum': {
            'c': True,
            'r': ['name', 'organization', 'achievements', 'tasks'],
            'u': ['name', 'organization', 'achievements', 'tasks'],
            'd': True,
        },
        'CurriculumEnrollment': {
            'c':
            True,
            'r': [
                'assignments', 'curriculum', 'users',
                'user_completion_statuses', 'start', 'end'
            ],
            'u': ['curriculum', 'users', 'start', 'end'],
            'd':
            True,
        },
        'CurriculumEnrollmentUserAssociation': {
            'c': True,
            'r': [],
            'u': [],
            'd': True,
        },
        'CurriculumTaskAssociation': {
            'c':
            True,
            'r': [
                'curriculum', 'task', 'task_bundle', 'days_to_complete',
                'days_before_start', 'presentation_order',
                'continue_automatically'
            ],
            'u': [
                'curriculum', 'task', 'task_bundle', 'days_to_complete',
                'days_before_start', 'presentation_order',
                'continue_automatically'
            ],
            'd':
            True,
        },
        'CustomAction': {
            'c': True,
            'r': ['name', 'description', 'function_name'],
            'u': ['name', 'description', 'function_name'],
            'd': True,
        },
        'Domain': {
            'c': True,
            'r': ['authentication_ip', 'name', 'users'],
            'u': ['authentication_password_hash', 'authentication_ip', 'name'],
            'd': True,
        },
        'DomainAffiliation': {
            'c': True,
            'r': ['default', 'domain', 'may_log_me_in', 'user', 'username'],
            'u': ['default', 'domain', 'may_log_me_in', 'user', 'username'],
            'd': True,
        },
        'FormPage': {
            'c': True,
            'r': ['exam', 'form_widgets', 'number', 'photo'],
            'u': ['exam', 'form_widgets', 'number'],
            'd': True,
        },
        'FormWidget': {
            'c': True,
            'r':
            ['answer', 'form_page', 'question', 'height', 'width', 'x', 'y'],
            'u':
            ['answer', 'form_page', 'question', 'height', 'width', 'x', 'y'],
            'd': True,
        },
        'forum.ForumPostAttachment': {
            'c': True,
            'r': ['description', 'name', 'post'],
            'u': ['description', 'name', 'post'],
            'd': True,
        },
        'forum.ForumCategory': {
            'c': True,
            'r': ['name', 'forums'],
            'u': ['name'],
            'd': True,
        },
        'forum.Forum': {
            'c': True,
            'r': ['category', 'description', 'name', 'topics'],
            'u': ['category', 'description', 'name'],
            'd': True,
        },
        'forum.ForumPost': {
            'c': True,
            'r': ['topic', 'body', 'attachments'],
            'u': ['topic', 'body'],
            'd': True,
        },
        'forum.ForumTopic': {
            'c': True,
            'r': ['closed', 'forum', 'name', 'posts', 'sticky'],
            'u': ['closed', 'forum', 'name', 'sticky'],
            'd': True,
        },
        'SessionTemplate': {
            'c':
            True,
            'r': [
                'active', 'audience', 'description', 'duration', 'fullname',
                'lead_time', 'sequence', 'price', 'product_line', 'shortname',
                'version', 'event_template',
                'session_template_resource_type_requirements',
                'session_template_user_role_requirements', 'sessions',
                'modality'
            ],
            'u': [
                'active', 'audience', 'description', 'duration', 'fullname',
                'lead_time', 'event_template', 'sequence', 'price',
                'product_line', 'shortname', 'version', 'modality'
            ],
            'd':
            True,
        },
        'SessionTemplateResourceTypeReq': {
            'c': True,
            'r': ['max', 'min', 'resource_type', 'session_template'],
            'u': ['max', 'min', 'resource_type', 'session_template'],
            'd': True,
        },
        'SessionTemplateUserRoleReq': {
            'c': True,
            'r': ['max', 'min', 'session_template', 'session_user_role'],
            'u': ['max', 'min', 'session_template', 'session_user_role'],
            'd': True,
        },
        'Credential': {
            'c':
            True,
            'r': [
                'authority', 'credential_type', 'date_assigned',
                'date_expires', 'date_granted', 'date_started',
                'serial_number', 'status', 'user', 'notes'
            ],
            'u': [
                'authority', 'credential_type', 'date_assigned',
                'date_expires', 'date_granted', 'date_started',
                'serial_number', 'status', 'user'
            ],
            'd':
            True,
        },
        'CredentialType': {
            'c':
            True,
            'r': [
                'description', 'name', 'notes', 'min_required_tasks',
                'required_achievements', 'prerequisite_credential_types'
            ],
            'u': [
                'description', 'name', 'notes', 'min_required_tasks',
                'required_achievements', 'prerequisite_credential_types'
            ],
            'd':
            True,
        },
        'EncodedVideo': {
            'c': True,
            'r': ['video', 'bitrate', 'url', 'http_url'],
            'u': [],
            'd': True,
        },
        'EventTemplate': {
            'c':
            True,
            'r': [
                'external_reference',
                'lag_time',
                'organization',
                'events',
                'lead_time',
                'name_prefix',
                'title',
                'description',
                'session_templates',
                'url',
                'product_line',
                'facebook_message',
                'twitter_message',
            ],
            'u': [
                'external_reference',
                'lag_time',
                'lead_time',
                'name_prefix',
                'organization',
                'title',
                'description',
                'url',
                'product_line',
                'facebook_message',
                'twitter_message',
            ],
            'd':
            True,
        },
        'Event': {
            'c':
            True,
            'r': [
                'external_reference',
                'region',
                'lag_time',
                'organization',
                'event_template',
                'lead_time',
                'name',
                'title',
                'description',
                'start',
                'end',
                'sessions',
                'owner',
                'venue',
                'status',
                'url',
                'product_line',
                'facebook_message',
                'twitter_message',
            ],
            'u': [
                'external_reference',
                'region',
                'lag_time',
                'lead_time',
                'name',
                'organization',
                'event_template',
                'owner',
                'title',
                'description',
                'start',
                'end',
                'venue',
                'url',
                'product_line',
                'facebook_message',
                'twitter_message',
            ],
            'd':
            True,
        },
        'Exam': {
            'c':
            True,
            'r': [
                'passing_score',
                'question_pools',
                'title',
                'achievements',
                'description',
                'name',
                'prerequisite_tasks',
                'type',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'u': [
                'passing_score',
                'question_pools',
                'title',
                'achievements',
                'description',
                'name',
                'prerequisite_tasks',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'd':
            True,
        },
        'ExamSession': {
            'c':
            True,
            'r': [
                'date_started', 'date_completed', 'exam', 'response_questions',
                'passing_score', 'number_correct', 'passed', 'score', 'user'
            ],
            'u': ['date_completed'],
            'd':
            True,
        },
        'Group': {
            'c': True,
            'r':
            ['categories', 'default', 'managers', 'name', 'users', 'notes'],
            'u': ['categories', 'default', 'managers', 'name', 'users'],
            'd': True,
        },
        'Note': {
            'c': True,
            'r': ['text'],
            'u': ['text'],
            'd': True,
        },
        'Organization': {
            'c':
            True,
            'r': [
                'address', 'department', 'description', 'email', 'fax', 'name',
                'notes', 'phone', 'photo_url', 'parent', 'children',
                'ancestors', 'descendants', 'org_email_domains',
                'primary_contact_first_name', 'primary_contact_last_name',
                'primary_contact_office_phone', 'primary_contact_cell_phone',
                'primary_contact_other_phone', 'primary_contact_email',
                'purchase_orders', 'training_unit_accounts', 'url', 'roles',
                'users', 'user_org_roles'
            ],
            'u': [
                'address', 'department', 'description', 'email', 'fax', 'name',
                'notes', 'phone', 'photo_url', 'parent',
                'primary_contact_first_name', 'primary_contact_last_name',
                'primary_contact_office_phone', 'primary_contact_cell_phone',
                'primary_contact_other_phone', 'primary_contact_email', 'url',
                'roles', 'users'
            ],
            'd':
            True,
        },
        'OrgEmailDomain': {
            'c':
            True,
            'r': [
                'email_domain', 'organization', 'role', 'effective_role',
                'effective_role_name'
            ],
            'u': ['email_domain', 'organization', 'role'],
            'd':
            True,
        },
        'OrgRole': {
            'c': True,
            'r': ['name', 'organizations', 'users', 'user_org_roles'],
            'u': ['name', 'organizations', 'users'],
            'd': True,
        },
        'Payment': {
            'c':
            True,
            'r': [
                'refunds', 'card_type', 'exp_date', 'amount', 'first_name',
                'last_name', 'city', 'state', 'zip', 'country', 'sales_tax',
                'transaction_id', 'invoice_number', 'result_message',
                'purchase_order', 'date'
            ],
            'u': [],
            'd':
            False,
        },
        'Product': {
            'c':
            True,
            'r': [
                'custom_actions', 'description', 'display_order', 'inventory',
                'cost', 'name', 'price', 'sku', 'starting_quantity',
                'training_units'
            ],
            'u': [
                'custom_actions', 'description', 'display_order', 'cost',
                'name', 'price', 'sku', 'starting_quantity', 'training_units'
            ],
            'd':
            True,
        },
        'ProductDiscount': {
            'c':
            True,
            'r': [
                'condition_test_collection', 'cumulative', 'currency',
                'percentage', 'products', 'product_offers', 'promo_code'
            ],
            'u': [
                'condition_test_collection', 'cumulative', 'currency',
                'percentage', 'products', 'product_offers', 'promo_code'
            ],
            'd':
            True,
        },
        'ProductLine': {
            'c':
            True,
            'r': [
                'instructor_managers', 'instructors', 'managers', 'name',
                'notes'
            ],
            'u': ['instructor_managers', 'instructors', 'managers', 'name'],
            'd':
            True,
        },
        'ProductOffer': {
            'c': True,
            'r': ['product', 'seller', 'description', 'price'],
            'u': ['product', 'seller', 'description', 'price'],
            'd': True,
        },
        'ProductClaim': {
            'c': True,
            'r': ['product', 'purchase_order', 'quantity'],
            'u': ['quantity'],
            'd': True,
        },
        'PurchaseOrder': {
            'c':
            True,
            'r': [
                'user', 'product_offers', 'products', 'promo_code',
                'product_discounts', 'organization', 'expiration', 'payments',
                'total_price', 'training_units_purchased',
                'training_units_price', 'is_paid'
            ],
            'u': [
                'user', 'organization', 'promo_code', 'expiration',
                'training_units_purchased', 'training_units_price'
            ],
            'd':
            True,
        },
        'Question': {
            'c':
            True,
            'r': [
                'answers', 'rejoinder', 'label', 'help_text', 'max_answers',
                'min_answers', 'max_length', 'min_length', 'max_value',
                'min_value', 'order', 'question_pool', 'question_type',
                'required', 'text_regex', 'text_response',
                'text_response_label', 'widget'
            ],
            'u': [
                'answers', 'rejoinder', 'label', 'help_text', 'max_answers',
                'min_answers', 'max_length', 'min_length', 'max_value',
                'min_value', 'order', 'question_pool', 'question_type',
                'required', 'text_regex', 'text_response',
                'text_response_label', 'widget'
            ],
            'd':
            True,
        },
        'QuestionPool': {
            'c':
            True,
            'r': [
                'exam', 'name', 'number_to_answer', 'order', 'questions',
                'randomize_questions', 'title'
            ],
            'u': [
                'exam', 'name', 'number_to_answer', 'order', 'questions',
                'randomize_questions', 'title'
            ],
            'd':
            True,
        },
        'Refund': {
            'c': True,
            'r': [],
            'u': [],
            'd': False,
        },
        'Region': {
            'c': True,
            'r': ['name', 'notes', 'events', 'venues'],
            'u': ['name', 'events', 'venues'],
            'd': True,
        },
        'Resource': {
            'c':
            True,
            'r': [
                'name', 'notes', 'resource_types',
                'session_resource_type_requirements'
            ],
            'u':
            ['name', 'resource_types', 'session_resource_type_requirements'],
            'd':
            True,
        },
        'ResourceType': {
            'c':
            True,
            'r': [
                'name', 'notes', 'resources',
                'sessionresourcetyperequirements',
                'sessiontemplateresourcetypereqs'
            ],
            'u': [
                'name', 'resources', 'sessionresourcetyperequirements',
                'sessiontemplateresourcetypereqs'
            ],
            'd':
            True,
        },
        'Response': {
            'c': True,
            'r':
            ['exam_session', 'correct', 'question', 'text', 'valid', 'value'],
            'u': [],
            'd': True,
        },
        'Role': {
            'c': True,
            'r': ['name', 'ac_check_methods', 'acl', 'notes'],
            'u': ['name', 'ac_check_methods', 'acl', 'notes'],
            'd': True,
        },
        'Room': {
            'c': True,
            'r': ['name', 'capacity', 'venue'],
            'u': ['name', 'capacity', 'venue'],
            'd': True,
        },
        'Sco': {
            'c':
            True,
            'r': [
                'achievements',
                'course',
                'completion_requirement',
                'data',
                'url',
                'description',
                'name',
                'title',
                'prerequisite_tasks',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'u': [
                'achievements',
                'completion_requirement',
                'description',
                'name',
                'title',
                'prerequisite_tasks',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'd':
            True,
        },
        'ScoSession': {
            'c':
            True,
            'r': [
                'cmi_core_lesson_location', 'cmi_core_lesson_status',
                'cmi_core_score_max', 'cmi_core_score_min', 'shared_object',
                'sco', 'date_completed', 'date_started'
            ],
            'u': ['date_completed', 'date_started'],
            'd':
            True,
        },
        'Session': {
            'c':
            True,
            'r': [
                'session_user_role_requirements', 'audience', 'confirmed',
                'session_template', 'default_price', 'description', 'end',
                'evaluation', 'modality', 'name', 'room', 'start', 'status',
                'title', 'url', 'event', 'paypal_url'
            ],
            'u': [
                'session_user_role_requirements', 'audience', 'confirmed',
                'session_template', 'default_price', 'description', 'end',
                'modality', 'name', 'room', 'start', 'status', 'title', 'url',
                'event'
            ],
            'd':
            True,
        },
        'SessionResourceTypeRequirement': {
            'c': True,
            'r': ['session', 'max', 'min', 'resource_type', 'resources'],
            'u': ['session', 'max', 'min', 'resource_type', 'resources'],
            'd': True,
        },
        'SessionUserRole': {
            'c': True,
            'r': ['name', 'session_user_role_requirements'],
            'u': ['name', 'session_user_role_requirements'],
            'd': True,
        },
        'SessionUserRoleRequirement': {
            'c':
            True,
            'r': [
                'credential_types', 'max', 'users', 'remaining_capacity',
                'session', 'session_user_role', 'min', 'ignore_room_capacity'
            ],
            'u': [
                'credential_types', 'max', 'users', 'session',
                'session_user_role', 'min', 'ignore_room_capacity'
            ],
            'd':
            True,
        },
        'Task': {
            'c':
            True,
            'r': [
                'description', 'name', 'title', 'prerequisite_tasks',
                'achievements', 'remaining_capacity', 'type', 'min', 'max',
                'version_id', 'version_label', 'version_comment',
                'yielded_tasks'
            ],
            'u': [
                'description', 'name', 'title', 'prerequisite_tasks',
                'achievements', 'version_id', 'version_label', 'min', 'max',
                'version_comment', 'yielded_tasks'
            ],
            'd':
            True,
        },
        'TaskBundle': {
            'c': True,
            'r': ['name', 'description', 'tasks'],
            'u': ['name', 'description', 'tasks'],
            'd': True,
        },
        'TaskFee': {
            'c':
            True,
            'r': [
                'custom_actions', 'description', 'display_order', 'inventory',
                'cost', 'name', 'price', 'sku', 'starting_quantity', 'task',
                'training_units'
            ],
            'u': [
                'custom_actions', 'description', 'display_order', 'cost',
                'name', 'price', 'sku', 'starting_quantity', 'task',
                'training_units'
            ],
            'd':
            True,
        },
        'TrainingUnitAccount': {
            'c': True,
            'r':
            ['organization', 'user', 'balance', 'training_unit_transactions'],
            'u': ['organization', 'user', 'starting_value'],
            'd': True,
        },
        'TrainingUnitAuthorization': {
            'c':
            True,
            'r': [
                'start', 'training_unit_account', 'end', 'user', 'used_value',
                'max_value'
            ],
            'u':
            ['start', 'training_unit_account', 'end', 'user', 'max_value'],
            'd':
            True,
        },
        'TrainingUnitTransaction': {
            'c': True,
            'r': ['training_unit_authorizations', 'value', 'purchase_order'],
            'u': ['training_unit_authorizations'],
            'd': True,
        },
        'TrainingVoucher': {
            'c':
            True,
            'r': [
                'price', 'session_user_role_requirement', 'code',
                'purchase_order'
            ],
            'u': ['session_user_role_requirement', 'purchase_order'],
            'd':
            True,
        },
        'User': {
            'c':
            True,
            'r': [
                'credentials', 'session_user_role_requirements',
                'product_lines_managed',
                'product_lines_instructor_manager_for',
                'product_lines_instructor_for', 'groups', 'roles', 'photo_url',
                'url', 'username', 'domains', 'title', 'first_name',
                'middle_name', 'last_name', 'name_suffix', 'full_name',
                'phone', 'phone2', 'phone3', 'email', 'email2', 'status',
                'color_code', 'biography', 'shipping_address',
                'billing_address', 'organizations', 'owned_userorgroles',
                'preferred_venues', 'completed_curriculum_enrollments',
                'incomplete_curriculum_enrollments', 'paypal_address',
                'enable_paypal', 'suppress_emails', 'is_staff',
                'default_username_and_domain', 'alleged_organization'
            ],
            'u': [
                'credentials', 'groups', 'roles', 'photo_url', 'url', 'title',
                'first_name', 'middle_name', 'last_name', 'name_suffix',
                'phone', 'phone2', 'phone3', 'email', 'email2', 'status',
                'color_code', 'biography', 'shipping_address',
                'billing_address', 'organizations', 'preferred_venues',
                'paypal_address', 'enable_paypal', 'suppress_emails',
                'is_staff', 'alleged_organization'
            ],
            'd':
            True,
        },
        'UserOrgRole': {
            'c':
            True,
            'r': [
                'owner', 'organization', 'organization_name', 'role',
                'role_name', 'parent', 'children'
            ],
            'u': ['owner', 'organization', 'role', 'parent'],
            'd':
            True,
        },
        'Venue': {
            'c':
            True,
            'r': [
                'contact', 'region', 'address', 'owner', 'phone', 'name',
                'events', 'rooms', 'hours_of_operation'
            ],
            'u': [
                'contact', 'region', 'address', 'owner', 'phone', 'name',
                'events', 'hours_of_operation'
            ],
            'd':
            True,
        },
        'Video': {
            'c':
            True,
            'r': [
                'id',
                'approved_categories',
                'aspect_ratio',
                'author',
                'categories',
                'category_relationships',
                'create_timestamp',
                'deleted',
                'description',
                'encoded_videos',
                'is_ready',
                'length',
                'live',
                'name',
                'title',
                'num_views',
                'owner',
                'photo_url',
                'prerequisite_tasks',
                'public',
                'src_file_size',
                'status',
                'tags',
                'users_who_watched',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'u': [
                'aspect_ratio',
                'author',
                'categories',
                'description',
                'encoded_videos',
                'length',
                'live',
                'name',
                'title',
                'owner',
                'photo_url',
                'prerequisite_tasks',
                'public',
                'tags',
                'version_id',
                'version_label',
                'version_comment',
            ],
            'd':
            True,
        },
        'VideoCategory': {
            'c': True,
            'r': ['status', 'category', 'category_name', 'video'],
            'u': ['status'],
            'd': True,
        },
        'VideoSession': {
            'c': True,
            'r':
            ['assignment', 'date_started', 'date_completed', 'user', 'video'],
            'u': ['date_started', 'date_completed'],
            'd': True,
        },
    }
    machine.add_acl_to_role('Admin', methods, crud, arb_perm_list)

    if not machine.options['authz_only']:
        # we need to reload ACLs that were just modified before using them to login
        facade.subsystems.Authorizer()._load_acls()

        # we log in here so that other setup methods can have an admin_token
        token_str = machine.user_manager.login('admin', password)['auth_token']
        machine.options['admin_token'] = Utils.get_auth_token_object(token_str)
def setup(machine):
    group, created = facade.models.Group.objects.get_or_create(
        name="Super Administrators")

    if not machine.options['authz_only']:
        if machine.options.has_key('default_admin_password'):        
            password = machine.options['default_admin_password']
        else:
            password = '******'
        salt = machine.user_manager._generate_password_salt()
        password_hash = Utils._hash(password + salt, 'SHA-512')

        user = facade.models.User.objects.create(first_name="admin",
            last_name="user", status='active', email='*****@*****.**')
        user.groups.add(group) # no need to save(), it's a ManyToManyField

        local_domain = facade.models.Domain.objects.get(name='local')
        da = facade.models.DomainAffiliation.objects.create(user=user,
            username='******', domain=local_domain, default=True,
            password_hash=password_hash, password_salt=salt)

    methods = [
        {'name' : 'actor_member_of_group', 'params' : {'group_id' : group.id}},
        {'name' : 'refund_does_not_exceed_payment', 'params' : {}},
    ]
    arb_perm_list = [
        'check_usernames',
        'change_password_of_other_users',
        'exceed_enrollment_capacity',
        'logging',
        'read_reports',
        'regenerate_payment_confirmations',
        'resend_payment_confirmations',
        'send_email',
        'upload_scorm_course',
    ]
    crud = {
        'Achievement' : {
            'c' : True,
            'r' : ['component_achievements', 'description', 'name', 'users', 'yielded_achievements'],
            'u' : ['component_achievements', 'description', 'name', 'users', 'yielded_achievements'],
            'd' : True,
        },
        'AchievementAward' : {
            'c' : True,
            'r' : ['assignment', 'date'],
            'u' : ['assignment', 'date'],
            'd' : True,
        },
        'Answer' : {
            'c' : True,
            'r' : ['correct', 'end_exam', 'end_question_pool', 'label',
                   'next_question_pool', 'order', 'question',
                   'text_response', 'value'],
            'u' : ['correct', 'end_exam', 'end_question_pool', 'label',
                   'next_question_pool', 'order', 'question',
                   'text_response', 'value'],
            'd' : True,
        },
        'Assignment' : {
            'c' : True,
            'r' : ['task', 'task_content_type', 'user', 'date_started',
                   'date_completed', 'due_date', 'prerequisites_met',
                   'effective_date_assigned', 'status', 'assignment_attempts'],
            'u' : ['due_date', 'effective_date_assigned', 'status', 'date_started',
                   'date_completed'],
            'd' : True,
        },
        'AssignmentAttempt' : {
            'c' : True,
            'r' : ['assignment', 'date_started', 'date_completed'],
            'u' : ['date_started', 'date_completed'],
            'd' : True,
        },
        'Category' : {
            'c' : True,
            'r' : ['authorized_groups', 'managers', 'name', 'locked', 'videos', 'approved_videos'],
            'u' : ['authorized_groups', 'managers', 'name', 'locked', 'videos'],
            'd' : True,
        },
        'ConditionTest' : {
            'c' : True,
            'r' : ['sequence', 'condition_test_collection', 'match_all_defined_parameters',
                    'groups', 'credentials', 'events', 'sessions',
                    'session_user_role_requirements', 'start', 'end'],
            'u' : ['sequence', 'condition_test_collection', 'match_all_defined_parameters',
                    'groups', 'credentials', 'events', 'sessions',
                    'session_user_role_requirements', 'start', 'end'],
            'd' : True,
        },
        'ConditionTestCollection' : {
            'c' : True,
            'r' : ['name', 'condition_tests'],
            'u' : ['name'],
            'd' : True,
        },
        'CSVData' : {
            'c' : True,
            'r' : [],
            'u' : [],
            'd' : True,
        },
        'Curriculum' : {
            'c' : True,
            'r' : ['name', 'organization', 'achievements', 'tasks'],
            'u' : ['name', 'organization', 'achievements', 'tasks'],
            'd' : True,
        },
        'CurriculumEnrollment' : {
            'c' : True,
            'r' : ['assignments', 'curriculum', 'users', 'user_completion_statuses', 'start', 'end'],
            'u' : ['curriculum', 'users', 'start', 'end'],
            'd' : True,
        },
        'CurriculumEnrollmentUserAssociation' : {
            'c' : True,
            'r' : [],
            'u' : [],
            'd' : True,
        },
        'CurriculumTaskAssociation' : {
            'c' : True,
            'r' : ['curriculum', 'task', 'task_bundle', 'days_to_complete', 'days_before_start', 'presentation_order', 'continue_automatically'],
            'u' : ['curriculum', 'task', 'task_bundle', 'days_to_complete', 'days_before_start', 'presentation_order', 'continue_automatically'],
            'd' : True,
        },
        'CustomAction' : {
            'c' : True,
            'r' : ['name', 'description', 'function_name'],
            'u' : ['name', 'description', 'function_name'],
            'd' : True,
        },
        'Domain' : {
            'c' : True,
            'r' : ['authentication_ip', 'name', 'users'],
            'u' : ['authentication_password_hash', 'authentication_ip', 'name'],
            'd' : True,
        },
        'DomainAffiliation' : {
            'c' : True,
            'r' : ['default', 'domain', 'may_log_me_in', 'user', 'username'],
            'u' : ['default', 'domain', 'may_log_me_in', 'user', 'username'],
            'd' : True,
        },
        'FormPage' : {
            'c' : True,
            'r' : ['exam', 'form_widgets', 'number', 'photo'],
            'u' : ['exam', 'form_widgets', 'number'],
            'd' : True,
        },
        'FormWidget' : {
            'c' : True,
            'r' : ['answer', 'form_page', 'question', 'height', 'width', 'x', 'y'],
            'u' : ['answer', 'form_page', 'question', 'height', 'width', 'x', 'y'],
            'd' : True,
        },
        'forum.ForumPostAttachment' : {
            'c' : True,
            'r' : ['description', 'name', 'post'],
            'u' : ['description', 'name', 'post'],
            'd' : True,
        },
        'forum.ForumCategory' : {
            'c' : True,
            'r' : ['name', 'forums'],
            'u' : ['name'],
            'd' : True,
        },
        'forum.Forum' : {
            'c' : True,
            'r' : ['category', 'description', 'name', 'topics'],
            'u' : ['category', 'description', 'name'],
            'd' : True,
        },
        'forum.ForumPost' : {
            'c' : True,
            'r' : ['topic', 'body', 'attachments'],
            'u' : ['topic', 'body'],
            'd' : True,
        },
        'forum.ForumTopic' : {
            'c' : True,
            'r' : ['closed', 'forum', 'name', 'posts', 'sticky'],
            'u' : ['closed', 'forum', 'name', 'sticky'],
            'd' : True,
        },
        'SessionTemplate' : {
            'c' : True,
            'r' : ['active', 'audience', 'description', 'duration', 'fullname', 'lead_time', 'sequence',
                    'price', 'product_line', 'shortname', 'version', 'event_template',
                    'session_template_resource_type_requirements', 'session_template_user_role_requirements',
                    'sessions', 'modality'],
            'u' : ['active', 'audience', 'description', 'duration', 'fullname', 'lead_time', 'event_template', 'sequence',
                   'price', 'product_line', 'shortname', 'version', 'modality'],
            'd' : True,
        },
        'SessionTemplateResourceTypeReq' : {
            'c' : True,
            'r' : ['max', 'min', 'resource_type', 'session_template'],
            'u' : ['max', 'min', 'resource_type', 'session_template'],
            'd' : True,
        },
        'SessionTemplateUserRoleReq' : {
            'c' : True,
            'r' : ['max', 'min', 'session_template', 'session_user_role'],
            'u' : ['max', 'min', 'session_template', 'session_user_role'],
            'd' : True,
        },
        'Credential' : {
            'c' : True,
            'r' : ['authority', 'credential_type', 'date_assigned',
                   'date_expires', 'date_granted', 'date_started',
                   'serial_number', 'status', 'user', 'notes'],
            'u' : ['authority', 'credential_type', 'date_assigned',
                   'date_expires', 'date_granted', 'date_started',
                   'serial_number', 'status', 'user'],
            'd' : True,
        },
        'CredentialType' : {
            'c' : True,
            'r' : ['description', 'name', 'notes', 'min_required_tasks',
                   'required_achievements', 'prerequisite_credential_types'],
            'u' : ['description', 'name', 'notes', 'min_required_tasks',
                   'required_achievements', 'prerequisite_credential_types'],
            'd' : True,
        },
        'EncodedVideo' : {
            'c' : True,
            'r' : ['video', 'bitrate', 'url', 'http_url'],
            'u' : [],
            'd' : True,
        },
        'EventTemplate' : {
            'c' : True,
            'r' : ['external_reference', 'lag_time', 'organization', 'events',
                    'lead_time', 'name_prefix', 'title', 'description', 'session_templates',
                    'url', 'product_line', 'facebook_message', 'twitter_message',],
            'u' : ['external_reference', 'lag_time', 'lead_time', 'name_prefix', 'organization',
                    'title', 'description', 'url', 'product_line', 'facebook_message', 'twitter_message',],
            'd' : True,
        },
        'Event' : {
            'c' : True,
            'r' : ['external_reference', 'region', 'lag_time', 'organization', 'event_template',
                      'lead_time', 'name', 'title', 'description', 'start', 'end', 'sessions',
                      'owner', 'venue', 'status', 'url', 'product_line', 'facebook_message', 'twitter_message',],
            'u' : ['external_reference', 'region', 'lag_time', 'lead_time', 'name', 'organization', 'event_template',
                   'owner', 'title', 'description', 'start', 'end', 'venue', 'url', 'product_line', 'facebook_message', 'twitter_message',],
            'd' : True,
        },
        'Exam' : {
            'c' : True,
            'r' : ['passing_score', 'question_pools', 'title', 'achievements',
                   'description', 'name', 'prerequisite_tasks', 'type',
                   'version_id', 'version_label', 'version_comment',],
            'u' : ['passing_score', 'question_pools', 'title', 'achievements',
                   'description', 'name', 'prerequisite_tasks',
                   'version_id', 'version_label', 'version_comment',],
            'd' : True,
        },
        'ExamSession' : {
            'c' : True,
            'r' : ['date_started', 'date_completed', 'exam', 'response_questions',
                      'passing_score', 'number_correct', 'passed', 'score', 'user'],
            'u' : ['date_completed'],
            'd' : True,
        },
        'Group' : {
            'c' : True,
            'r' : ['categories', 'default', 'managers', 'name', 'users', 'notes'],
            'u' : ['categories', 'default', 'managers', 'name', 'users'],
            'd' : True,
        },
        'Note' : {
            'c' : True,
            'r' : ['text'],
            'u' : ['text'],
            'd' : True,
        },
        'Organization' : {
            'c' : True,
            'r' : ['address', 'department', 'description', 'email', 'fax', 'name', 'notes', 'phone', 'photo_url',
                    'parent', 'children', 'ancestors', 'descendants', 'org_email_domains',
                    'primary_contact_first_name', 'primary_contact_last_name', 'primary_contact_office_phone',
                    'primary_contact_cell_phone', 'primary_contact_other_phone', 'primary_contact_email',
                    'purchase_orders', 'training_unit_accounts', 'url', 'roles', 'users', 'user_org_roles'],
            'u' : ['address', 'department', 'description', 'email', 'fax', 'name', 'notes', 'phone', 'photo_url', 'parent',
                    'primary_contact_first_name', 'primary_contact_last_name', 'primary_contact_office_phone', 'primary_contact_cell_phone',
                    'primary_contact_other_phone', 'primary_contact_email', 'url', 'roles', 'users'],
            'd' : True,
        },
        'OrgEmailDomain' : {
            'c' : True,
            'r' : ['email_domain', 'organization', 'role', 'effective_role', 'effective_role_name'],
            'u' : ['email_domain', 'organization', 'role'],
            'd' : True,
        },
        'OrgRole' : {
            'c' : True,
            'r' : ['name', 'organizations', 'users', 'user_org_roles'],
            'u' : ['name', 'organizations', 'users'],
            'd' : True,
        },
        'Payment' : {
            'c' : True,
            'r' : ['refunds', 'card_type', 'exp_date', 'amount',
                      'first_name', 'last_name', 'city', 'state', 'zip', 'country',
                      'sales_tax', 'transaction_id', 'invoice_number', 'result_message', 'purchase_order',
                      'date'],
            'u' : [],
            'd' : False,
        },
        'Product' : {
            'c' : True,
            'r' : ['custom_actions', 'description', 'display_order', 'inventory', 'cost', 'name', 'price', 'sku', 'starting_quantity', 'training_units'],
            'u' : ['custom_actions', 'description', 'display_order', 'cost', 'name', 'price', 'sku', 'starting_quantity', 'training_units'],
            'd' : True,
        },
        'ProductDiscount' : {
            'c' : True,
            'r' : ['condition_test_collection', 'cumulative', 'currency', 'percentage', 'products', 'product_offers', 'promo_code'],
            'u' : ['condition_test_collection', 'cumulative', 'currency', 'percentage', 'products', 'product_offers', 'promo_code'],
            'd' : True,
        },
        'ProductLine' : {
            'c' : True,
            'r' : ['instructor_managers', 'instructors', 'managers',
                      'name', 'notes'],
            'u' : ['instructor_managers', 'instructors', 'managers', 'name'],
            'd' : True,
        },
        'ProductOffer' : {
            'c' : True,
            'r' : ['product', 'seller', 'description', 'price'],
            'u' : ['product', 'seller', 'description', 'price'],
            'd' : True,
        },
        'ProductClaim' : {
            'c' : True,
            'r' : ['product', 'purchase_order', 'quantity'],
            'u' : ['quantity'],
            'd' : True,
        },
        'PurchaseOrder' : {
            'c' : True,
            'r' : ['user', 'product_offers', 'products', 'promo_code',
                      'product_discounts', 'organization',
                      'expiration', 'payments', 'total_price', 'training_units_purchased',
                      'training_units_price', 'is_paid'],
            'u' : ['user', 'organization', 'promo_code',
                    'expiration', 'training_units_purchased', 'training_units_price'],
            'd' : True,
        },
        'Question' : {
            'c' : True,
            'r' : ['answers', 'rejoinder', 'label', 'help_text',
                   'max_answers', 'min_answers', 'max_length', 'min_length',
                   'max_value', 'min_value', 'order', 'question_pool',
                   'question_type', 'required', 'text_regex',
                   'text_response', 'text_response_label', 'widget'],
            'u' : ['answers', 'rejoinder', 'label', 'help_text',
                   'max_answers', 'min_answers', 'max_length', 'min_length',
                   'max_value', 'min_value', 'order', 'question_pool',
                   'question_type', 'required', 'text_regex',
                   'text_response', 'text_response_label', 'widget'],
            'd' : True,
        },
        'QuestionPool' : {
            'c' : True,
            'r' : ['exam', 'name', 'number_to_answer', 'order',
                   'questions', 'randomize_questions', 'title'],
            'u' : ['exam', 'name', 'number_to_answer', 'order',
                   'questions', 'randomize_questions', 'title'],
            'd' : True,
        },
        'Refund' : {
            'c' : True,
            'r' : [],
            'u' : [],
            'd' : False,
        },
        'Region' : {
            'c' : True,
            'r' : ['name', 'notes', 'events', 'venues'],
            'u' : ['name', 'events', 'venues'],
            'd' : True,
        },
        'Resource' : {
            'c' : True,
            'r' : ['name', 'notes', 'resource_types',
                   'session_resource_type_requirements'],
            'u' : ['name', 'resource_types',
                   'session_resource_type_requirements'],
            'd' : True,
        },
        'ResourceType' : {
            'c' : True,
            'r' : ['name', 'notes', 'resources',
                   'sessionresourcetyperequirements',
                   'sessiontemplateresourcetypereqs'],
            'u' : ['name', 'resources', 'sessionresourcetyperequirements',
                   'sessiontemplateresourcetypereqs'],
            'd' : True,
        },
        'Response' : {
            'c' : True,
            'r' : ['exam_session', 'correct', 'question', 'text', 'valid',
                   'value'],
            'u' : [],
            'd' : True,
        },
        'Role' : {
            'c' : True,
            'r' : ['name', 'ac_check_methods', 'acl', 'notes'],
            'u' : ['name', 'ac_check_methods', 'acl', 'notes'],
            'd' : True,
        },
        'Room' : {
            'c' : True,
            'r' : ['name', 'capacity', 'venue'],
            'u' : ['name', 'capacity', 'venue'],
            'd' : True,
        },
        'Sco' : {
            'c' : True,
            'r' : ['achievements', 'course', 'completion_requirement', 'data', 'url',
                   'description', 'name', 'title', 'prerequisite_tasks',
                   'version_id', 'version_label', 'version_comment',],
            'u' : ['achievements', 'completion_requirement', 'description', 'name', 'title',
                   'prerequisite_tasks', 'version_id', 'version_label',
                   'version_comment',],
            'd' : True,
        },
        'ScoSession' : {
            'c' : True,
            'r' : ['cmi_core_lesson_location',
                      'cmi_core_lesson_status', 'cmi_core_score_max', 'cmi_core_score_min',
                      'shared_object', 'sco', 'date_completed', 'date_started'],
            'u' : ['date_completed', 'date_started'],
            'd' : True,
        },
        'Session' : {
            'c' : True,
            'r' : ['session_user_role_requirements', 'audience',
                      'confirmed', 'session_template', 'default_price',
                    'description', 'end', 'evaluation', 'modality', 'name',
                    'room', 'start', 'status', 'title', 'url', 'event',
                    'paypal_url'],
            'u' : [ 'session_user_role_requirements', 'audience', 'confirmed', 'session_template', 'default_price', 'description',
                    'end', 'modality', 'name', 'room', 'start', 'status',
                    'title', 'url', 'event'],
            'd' : True,
        },
        'SessionResourceTypeRequirement' : {
            'c' : True,
            'r' : ['session', 'max', 'min', 'resource_type', 'resources'],
            'u' : ['session', 'max', 'min', 'resource_type', 'resources'],
            'd' : True,
        },
        'SessionUserRole' : {
            'c' : True,
            'r' : ['name', 'session_user_role_requirements'],
            'u' : ['name', 'session_user_role_requirements'],
            'd' : True,
        },
        'SessionUserRoleRequirement' : {
            'c' : True,
            'r' : ['credential_types', 'max', 'users',
                      'remaining_capacity', 'session', 'session_user_role', 'min',
                      'ignore_room_capacity'],
            'u' : ['credential_types', 'max', 'users', 'session',
                      'session_user_role', 'min', 'ignore_room_capacity'],
            'd' : True,
        },
        'Task' : {
            'c' : True,
            'r' : ['description', 'name', 'title', 'prerequisite_tasks', 'achievements',
                   'remaining_capacity', 'type', 'min', 'max',
                   'version_id', 'version_label', 'version_comment', 'yielded_tasks'],
            'u' : ['description', 'name', 'title', 'prerequisite_tasks', 'achievements',
                   'version_id', 'version_label', 'min', 'max',
                   'version_comment', 'yielded_tasks'],
            'd' : True,
        },
        'TaskBundle': {
            'c': True,
            'r': ['name', 'description', 'tasks'],
            'u': ['name', 'description', 'tasks'],
            'd': True,
        },
        'TaskFee' : {
            'c' : True,
            'r' : ['custom_actions', 'description', 'display_order', 'inventory', 'cost', 'name', 'price', 'sku', 'starting_quantity', 'task', 'training_units'],
            'u' : ['custom_actions', 'description', 'display_order', 'cost', 'name', 'price', 'sku', 'starting_quantity', 'task', 'training_units'],
            'd' : True,
        },
        'TrainingUnitAccount' : {
            'c' : True,
            'r' : ['organization', 'user', 'balance',
                      'training_unit_transactions'],
            'u' : ['organization', 'user', 'starting_value'],
            'd' : True,
        },
        'TrainingUnitAuthorization' : {
            'c' : True,
            'r' : ['start', 'training_unit_account', 'end', 'user',
                      'used_value', 'max_value'],
            'u' : ['start', 'training_unit_account', 'end', 'user', 'max_value'],
            'd' : True,
        },
        'TrainingUnitTransaction' : {
            'c' : True,
            'r' : ['training_unit_authorizations',
                      'value', 'purchase_order'],
            'u' : ['training_unit_authorizations'],
            'd' : True,
        },
        'TrainingVoucher' : {
            'c' : True,
            'r' : ['price', 'session_user_role_requirement',
                      'code', 'purchase_order'],
            'u' : ['session_user_role_requirement', 'purchase_order'],
            'd' : True,
        },
        'User' : {
            'c' : True,
            'r' : ['credentials',
                   'session_user_role_requirements', 'product_lines_managed',
                   'product_lines_instructor_manager_for',
                   'product_lines_instructor_for', 'groups',
                   'roles', 'photo_url', 'url', 'username', 'domains',
                   'title', 'first_name', 'middle_name', 'last_name',
                   'name_suffix', 'full_name',
                   'phone', 'phone2', 'phone3', 'email', 'email2', 'status',
                   'color_code', 'biography',
                   'shipping_address', 'billing_address', 'organizations', 'owned_userorgroles',
                   'preferred_venues',
                   'completed_curriculum_enrollments',
                   'incomplete_curriculum_enrollments', 'paypal_address', 'enable_paypal',
                   'suppress_emails', 'is_staff',
                   'default_username_and_domain', 'alleged_organization'],
            'u' : [ 'credentials',
                    'groups', 'roles', 'photo_url',
                    'url',
                    'title', 'first_name', 'middle_name', 'last_name', 'name_suffix',
                    'phone', 'phone2', 'phone3',
                    'email', 'email2', 'status', 'color_code', 'biography',
                    'shipping_address', 'billing_address', 'organizations',
                    'preferred_venues',
                    'paypal_address',
                    'enable_paypal', 'suppress_emails', 'is_staff', 'alleged_organization'],
            'd' : True,
        },
        'UserOrgRole' : {
            'c' : True,
            'r' : ['owner', 'organization', 'organization_name', 'role', 'role_name', 'parent', 'children'],
            'u' : ['owner', 'organization', 'role', 'parent'],
            'd' : True,
        },
        'Venue' : {
            'c' : True,
            'r' : ['contact', 'region', 'address', 'owner', 'phone',
                      'name', 'events', 'rooms', 'hours_of_operation'],
            'u' : ['contact', 'region', 'address', 'owner', 'phone', 'name', 'events', 'hours_of_operation'],
            'd' : True,
        },
        'Video' : {
            'c' : True,
            'r' : ['id', 'approved_categories', 'aspect_ratio', 'author',
                   'categories', 'category_relationships', 'create_timestamp',
                   'deleted', 'description',
                   'encoded_videos', 'is_ready', 'length', 'live', 'name', 'title', 'num_views', 'owner',
                   'photo_url', 'prerequisite_tasks', 'public', 'src_file_size',
                   'status', 'tags', 'users_who_watched',
                   'version_id', 'version_label', 'version_comment',],
            'u' : ['aspect_ratio', 'author', 'categories', 'description',
                   'encoded_videos', 'length', 'live', 'name', 'title', 'owner',
                   'photo_url', 'prerequisite_tasks', 'public',
                   'tags', 'version_id', 'version_label', 'version_comment',],
            'd' : True,
        },
        'VideoCategory' : {
            'c' : True,
            'r' : ['status', 'category', 'category_name', 'video'],
            'u' : ['status'],
            'd' : True,
        },
        'VideoSession' : {
            'c' : True,
            'r' : ['assignment', 'date_started', 'date_completed', 'user', 'video'],
            'u' : ['date_started', 'date_completed'],
            'd' : True,
        },
    }
    machine.add_acl_to_role('Admin', methods, crud, arb_perm_list)

    if not machine.options['authz_only']:
        # we need to reload ACLs that were just modified before using them to login
        facade.subsystems.Authorizer()._load_acls()

        # we log in here so that other setup methods can have an admin_token
        token_str = machine.user_manager.login('admin', password)['auth_token']
        machine.options['admin_token'] = Utils.get_auth_token_object(token_str)
    def vod_admin_groups_view(self, auth_token):
        groups = self.get_filtered(auth_token, {}, ['name', 'categories'])

        return Utils.merge_queries(groups, facade.managers.CategoryManager(), auth_token, 
            ['name'], 'categories')
def upload_csv(request, auth_token=None, model_name=None):
    """Handle CSV file uploads

    This method will stick the contents of the uploaded file (of which there
    must be exactly 1) into the database through a csv_data object.  There is
    currently no validation on this end, but Django will raise an exception
    if you try to upload binary data.

    :param request:   HttpRequest object from Django

    """
    log_prefix = u'pr_services.utils.upload.upload_csv(): '

    logging.debug(log_prefix + 'model name [%s]' % str(model_name))

    if request.method == 'GET':
        if auth_token is None:
            return _render_response_forbidden(
                request,
                msg='Your request must include an auth token in its URL.')
        if model_name is None:
            return _render_response_bad_request(
                request,
                msg=
                'Your request must include a model name as the last component of its URL.'
            )
        return _render_response(
            request, 'upload_csv.html', {
                'title': 'CSV File Upload',
                'form': CsvUploadForm(),
                'model_name': model_name,
                'auth_token': auth_token
            })

    elif request.method == 'POST':
        if auth_token is None:
            if 'auth_token' in request.POST:
                auth_token = request.POST['auth_token']
            else:
                return _render_response_forbidden(
                    request,
                    msg=
                    'Your request must contain a variable named "auth_token".')

        if len(request.FILES) != 1:
            return _render_response_bad_request(
                request, msg='Your request must include exactly one file.')

        if model_name is None:
            if 'model' in request.POST:
                model_name = request.POST['model']
            else:
                return _render_response_bad_request(request,
                    msg='Your request must include a variable named "model", ' + \
                    'specifying which type of model you are uploading.')

    try:
        auth_token = Utils.get_auth_token_object(auth_token)

        # There should only be one file, so this loop exists just because we don't
        # know the file name under which it is indexed.
        c = None
        for filename in request.FILES:
            c = _process_csv_file(auth_token, request.FILES[filename],
                                  model_name)

        return _render_response_ok(request, msg=(str(c) if c else None))
    except exceptions.PrException, p:
        log_message = log_prefix + 'PR exception encountered: '
        if request.method == 'POST':
            if 'auth_token' in request.POST:
                log_message += 'auth_token: [%s]' % request.POST['auth_token']
        log_message += u' error code [%s], message [%s], details [%s]' %\
            (unicode(p.get_error_code()), p.get_error_msg(), unicode(p.get_details()))
        logging.info(log_message)

        return _render_response_forbidden(request, msg=p.get_error_msg())
def _upload_photo(request, actee_manager, actee_index_name, model_photo_storage_engine,
    auth_token=None, actee_index=None):
    """Handle Image file uploads for generic models that have a 'photo' attribute.

    This method will stick the contents of the uploaded file (of which there
    must be exactly 1) onto the filesystem, using Django's "ImageField".

    This method does no validation by design, as that is expected to happen
    in the storage system

    :param request:                     HttpRequest object from Django
    :param actee_manager:               An instance of the manager by which we can look up the actee
    :type actee_manager:                An ObjectManager subclass
    :param actee_index_name:            The key to use on the POST request to find the primary key of the model that we wish to upload
                                        the photo for
    :type actee_index_name:             string
    :param model_photo_storage_engine:  One of the storage engines from storage.py
    :type model_photo_storage_engine:   One of the storage engines from storage.py

    """
    logger = logging.getLogger('utils.upload.upload_photo')

    try:
        if auth_token is None:
            auth_token = request.POST.get('auth_token', None)
        if actee_index is None:
            actee_index = request.POST.get(actee_index_name, None)
        if request.method == 'POST' and len(request.FILES) == 1 and auth_token and actee_index:
            actee = actee_manager._find_by_id(actee_index)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(auth_token, actee, {'photo_url' : 'A New Photo!'})
            # save the old photo so we can blow it away on success
            try:
                oldphoto = actee.photo.path
            except ValueError:
                # User has no photo
                oldphoto = None

            # There should only be one file, so a single popitem should
            # provide the photo object tuple. In this, the first item is
            # the form value name, and the second is a list with one entry
            # That entry is our file object.

            # TODO Getting the name of the file input field should be doable.
            # We shouldn't have to assume we have to popitem().
            photo = request.FILES.popitem()[1][0]
            try:
                actee.photo.save(photo.name, photo, save=True)
            # TODO This deserves an explanation.
            except AttributeError:
                actee.photo.save(str(photo), photo, save=True)

            if oldphoto:
                try:
                    model_photo_storage_engine.delete(oldphoto)
                except OSError, e:
                    logger.debug('cannot delete photo %s because it is still in use by another process. This is a Windows-specific error. Please let us know if you see this message on a platform besides Windows.' % (oldphoto))

            return _render_response_ok(request, msg='Image upload successful.')

        else:
    def upload_video(self, request, auth_token=None):
        """Handle video file uploads

        This method will stick the contents of the uploaded file (of which there
        must be exactly 1) into the database through a Video object.  There is
        currently no validation of the Video.

        :param request: HttpRequest object from Django
        :type request:  HttpRequest
        :param auth_token:  AuthToken from an HTML form upload
        :type auth_token:   string or None

        """
        try:
            if request.method == 'GET':
                transaction.rollback()
                if auth_token is None:
                    return upload._render_response_forbidden(
                        request,
                        msg=
                        'Your request must include an auth token in its URL.')
                return upload._render_response(
                    request, 'vod_upload_video.html', {
                        'title': 'Video Upload',
                        'form': VideoUploadForm(),
                        'auth_token': auth_token
                    })
            elif request.method == 'POST':
                if auth_token is None:
                    if 'auth_token' not in request.POST:
                        transaction.rollback()
                        return upload._render_response_forbidden(
                            request,
                            msg=
                            'Your request must contain a variable named \'auth_token\'.'
                        )
                    else:
                        auth_token = request.POST['auth_token']
                form = VideoUploadForm(data=request.POST, files=request.FILES)
                if form.is_valid():
                    at = Utils.get_auth_token_object(auth_token)
                    at.domain_affiliation.user = at.domain_affiliation.user.downcast_completely(
                    )
                    if 'categories' in request.POST:
                        try:
                            categories = json.loads(request.POST['categories'])
                        except ValueError:  # Will also handle json.JSONDecodeError, depending on simplejson version used.
                            raise exceptions.InvalidDataException, 'invalid JSON data in categories field'
                        if not isinstance(categories, list):
                            raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        for c in categories:
                            if not (isinstance(c, dict) and 'id' in c
                                    and type(c['id']) in (int, long)):
                                raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        categories = [c['id'] for c in categories]
                    new_video = self.create(at, form.cleaned_data['name'],
                                            form.cleaned_data['description'],
                                            form.cleaned_data['author'],
                                            categories)
                    new_video.src_file_size = form.files['video'].size
                    new_video.save()
                    # Commit the transaction before queuing a task to work on
                    # our new Video object.
                    transaction.commit()
                    if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW',
                               True):
                        ## Queue the task to upload the video to S3.
                        # Let's get the notification URL here because we can do
                        # it accurately while in the web hosting environment
                        # but not in celeryd.
                        notify_url = getattr(settings,
                                             'ENCODING_NOTIFICATION_URL',
                                             False)
                        if not notify_url:
                            request = middleware.get_current_request()
                            site = '%s://%s' % (request.is_secure() and 'https'
                                                or 'http', request.get_host())
                            notify_url = urlparse.urljoin(
                                site, reverse('vod_aws:video_notification'))
                        pending = prepare_upload(new_video,
                                                 'src_file',
                                                 'video/%d.src' % new_video.id,
                                                 form.files['video'],
                                                 callback=subtask(
                                                     queue_encoding,
                                                     video_id=new_video.id,
                                                     notify_url=notify_url))
                        transaction.commit()
                        pending.queue()

                    if 'auth_token' not in request.POST:
                        return upload._render_response_ok(
                            request, msg='Video upload successful.')
                    else:
                        # for plain POST requests (old way), still return the video ID
                        return HttpResponse(
                            str(new_video.id) if new_video else None)
                else:
                    transaction.rollback()
                    logging.info(str(form.errors))
                    return upload._render_response(request,
                                                   'vod_upload_video.html', {
                                                       'title': 'Video Upload',
                                                       'form': form,
                                                       'auth_token': auth_token
                                                   },
                                                   status=400)
        except exceptions.PrException, p:
            transaction.rollback()
            log_message = u'UploadManager.upload_video: pr exception code %d, msg [%s], details [%s]' %\
                (p.get_error_code(), p.get_error_msg(), unicode(p.get_details()))
            logging.info(log_message)
            if p.error_code == 46:  # InternalErrorException
                stack_trace = traceback.format_exc()
                logging.info(stack_trace)
                return upload._render_response_server_error(
                    request, msg=p.get_error_msg())
            elif p.error_code in [17, 23, 49, 114, 115, 128]:
                return upload._render_response_forbidden(request,
                                                         msg=p.get_error_msg())
            else:
                return upload._render_response_bad_request(
                    request, msg=p.get_error_msg())
    def upload_video(self, request, auth_token=None):
        """Handle video file uploads

        This method will stick the contents of the uploaded file (of which there
        must be exactly 1) into the database through a Video object.  There is
        currently no validation of the Video.

        :param request: HttpRequest object from Django
        :type request:  HttpRequest
        :param auth_token:  AuthToken from an HTML form upload
        :type auth_token:   string or None

        """
        try:
            if request.method == 'GET':
                transaction.rollback()
                if auth_token is None:
                    return upload._render_response_forbidden(request,
                        msg='Your request must include an auth token in its URL.')
                return upload._render_response(request, 'vod_upload_video.html',
                    {'title': 'Video Upload', 'form': VideoUploadForm(),
                     'auth_token': auth_token})
            elif request.method == 'POST':
                if auth_token is None:
                    if 'auth_token' not in request.POST:
                        transaction.rollback()
                        return upload._render_response_forbidden(request,
                            msg='Your request must contain a variable named \'auth_token\'.')
                    else:
                        auth_token = request.POST['auth_token']
                form = VideoUploadForm(data=request.POST, files=request.FILES)
                if form.is_valid():
                    at = Utils.get_auth_token_object(auth_token)
                    at.domain_affiliation.user = at.domain_affiliation.user.downcast_completely()
                    if 'categories' in request.POST:
                        try:
                            categories = json.loads(request.POST['categories'])
                        except ValueError: # Will also handle json.JSONDecodeError, depending on simplejson version used.
                            raise exceptions.InvalidDataException, 'invalid JSON data in categories field'
                        if not isinstance(categories, list):
                            raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        for c in categories:
                            if not (isinstance(c, dict) and
                                'id' in c and
                                type(c['id']) in (int, long)):
                                    raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        categories = [c['id'] for c in categories]
                    new_video = self.create(at,
                        form.cleaned_data['name'],
                        form.cleaned_data['description'],
                        form.cleaned_data['author'],
                        categories)
                    new_video.src_file_size = form.files['video'].size
                    new_video.save()
                    # Commit the transaction before queuing a task to work on
                    # our new Video object.
                    transaction.commit()
                    if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                        ## Queue the task to upload the video to S3.
                        # Let's get the notification URL here because we can do
                        # it accurately while in the web hosting environment
                        # but not in celeryd.
                        notify_url = getattr(settings, 'ENCODING_NOTIFICATION_URL', False)
                        if not notify_url:
                            request = middleware.get_current_request()
                            site = '%s://%s' % (
                                request.is_secure() and 'https' or 'http',
                                request.get_host())
                            notify_url = urlparse.urljoin(site, reverse('vod_aws:video_notification'))
                        pending = prepare_upload(new_video, 'src_file',
                            'video/%d.src' % new_video.id,
                            form.files['video'],
                            callback=subtask(queue_encoding,
                                video_id=new_video.id, notify_url=notify_url))
                        transaction.commit()
                        pending.queue()

                    if 'auth_token' not in request.POST:
                        return upload._render_response_ok(request,
                            msg='Video upload successful.')
                    else:
                        # for plain POST requests (old way), still return the video ID
                        return HttpResponse(str(new_video.id) if new_video else None)
                else:
                    transaction.rollback()
                    logging.info(str(form.errors))
                    return upload._render_response(request, 'vod_upload_video.html',
                        {'title': 'Video Upload', 'form': form,
                         'auth_token': auth_token}, status=400)
        except exceptions.PrException, p:
            transaction.rollback()
            log_message = u'UploadManager.upload_video: pr exception code %d, msg [%s], details [%s]' %\
                (p.get_error_code(), p.get_error_msg(), unicode(p.get_details()))
            logging.info(log_message)
            if p.error_code == 46: # InternalErrorException
                stack_trace = traceback.format_exc()
                logging.info(stack_trace)
                return upload._render_response_server_error(request, msg=p.get_error_msg())
            elif p.error_code in [17, 23, 49, 114, 115, 128]:
                return upload._render_response_forbidden(request, msg=p.get_error_msg())
            else:
                return upload._render_response_bad_request(request, msg=p.get_error_msg())
def _upload_photo(request,
                  actee_manager,
                  actee_index_name,
                  model_photo_storage_engine,
                  auth_token=None,
                  actee_index=None):
    """Handle Image file uploads for generic models that have a 'photo' attribute.

    This method will stick the contents of the uploaded file (of which there
    must be exactly 1) onto the filesystem, using Django's "ImageField".

    This method does no validation by design, as that is expected to happen
    in the storage system

    :param request:                     HttpRequest object from Django
    :param actee_manager:               An instance of the manager by which we can look up the actee
    :type actee_manager:                An ObjectManager subclass
    :param actee_index_name:            The key to use on the POST request to find the primary key of the model that we wish to upload
                                        the photo for
    :type actee_index_name:             string
    :param model_photo_storage_engine:  One of the storage engines from storage.py
    :type model_photo_storage_engine:   One of the storage engines from storage.py

    """
    logger = logging.getLogger('utils.upload.upload_photo')

    try:
        if auth_token is None:
            auth_token = request.POST.get('auth_token', None)
        if actee_index is None:
            actee_index = request.POST.get(actee_index_name, None)
        if request.method == 'POST' and len(
                request.FILES) == 1 and auth_token and actee_index:
            actee = actee_manager._find_by_id(actee_index)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(
                auth_token, actee, {'photo_url': 'A New Photo!'})
            # save the old photo so we can blow it away on success
            try:
                oldphoto = actee.photo.path
            except ValueError:
                # User has no photo
                oldphoto = None

            # There should only be one file, so a single popitem should
            # provide the photo object tuple. In this, the first item is
            # the form value name, and the second is a list with one entry
            # That entry is our file object.

            # TODO Getting the name of the file input field should be doable.
            # We shouldn't have to assume we have to popitem().
            photo = request.FILES.popitem()[1][0]
            try:
                actee.photo.save(photo.name, photo, save=True)
            # TODO This deserves an explanation.
            except AttributeError:
                actee.photo.save(str(photo), photo, save=True)

            if oldphoto:
                try:
                    model_photo_storage_engine.delete(oldphoto)
                except OSError, e:
                    logger.debug(
                        'cannot delete photo %s because it is still in use by another process. This is a Windows-specific error. Please let us know if you see this message on a platform besides Windows.'
                        % (oldphoto))

            return _render_response_ok(request, msg='Image upload successful.')

        else: