def copy(): """ URLs: - /comic/copy?id=123 Function: - Ask the user which box to file a copy of a comic into, and then perform the copy operation. """ # Find out which comic is being copied. requested_comic = request.vars.get('id') # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404. if comic is None: raise HTTP(404) # Get the id of the current user. current_user = auth.user_id # Get the details of the comic's owner. owner = db_access.get_user(comic.owner_id) # Set the title of the page. response.title = 'Copy Comic' # Remind the user what comic they are copying. response.subtitle = 'Copying {title} #{issue} from {name}'.format(title=comic.title, issue=comic.issue_number, name=owner.username) # Create a box selection form populated with a list of the user's boxes. form = box_selection_form(db, current_user, submit_button='Copy') # The form has no validation so it will always be accepted. if form.process().accepted: # Perform the copy operation, assigning the comic to the new user. new_comic_id = db_access.copy_comic(comic_id, current_user) # Create a filing between the new comic and the selected box. db_access.create_filing(new_comic_id, form.vars.box_id) # Take the user to their new comic. redirect(URL('comic', 'index', vars={'id': new_comic_id})) return dict(form=form)
def delete(): """ URLs: - /comic/delete?id=123 Function: - Perform the deletion of a comic after the user has confirmed they want it to be deleted. Notes: - This function should only be reached by redirection from comic/confirm_delete. Unfortunately there's no way to stop someone manually typing in the URL. """ # Find out which comic is being deleted. requested_comic = request.vars.get('id') # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404. if comic is None: raise HTTP(404) # Get the id of the current user. current_user = auth.user_id # If the comic doesn't belong to the current user, redirect to the private page. if comic.owner_id != current_user: redirect(URL('private', 'index', args='comic', vars={'edit': 'true'})) # Set the title of the page. response.title = 'Deleted' # Actually delete the comic. db_access.delete_comic(comic.id) return dict(comic=comic)
def confirm_delete(): """ URLs: - /comic/confirm_delete?id=123 Function: - Used to confirm that the user wants to delete a comic, providing a Delete button and a Cancel button. If the user chooses Delete, they will be redirected to /comic/delete which will actually delete the box. Notes: - If the comic does not belong to the logged in user, they will be redirected to /private/comic. """ # Find out which comic is being deleted. requested_comic = request.vars.get('id') # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404. if comic is None: raise HTTP(404) # Get the id of the current user. current_user = auth.user_id # If the comic doesn't belong to the current user, redirect to the private page. if comic.owner_id != current_user: redirect(URL('private', 'index', args='comic', vars={'edit': 'true'})) # Set the title of the page. response.title = 'Delete Comic' return dict(comic=comic)
def file(): """ URLs: - /comic/file?id=123 Function: - Allow the user to select which boxes to file a comic into. """ # Find out which comic is being filed. requested_comic = request.vars.get('id') # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404. if comic is None: raise HTTP(404) # Get the id of the current user. current_user = auth.user_id # If the comic doesn't belong to the current user, redirect to the private page. if comic.owner_id != current_user: redirect(URL('private', 'index', args='comic', vars={'edit': 'true'})) # Set the title of the page. response.title = 'File Comic' response.subtitle = 'Choose boxes to file {title} #{issue} into'.format(title=comic.title, issue=comic.issue_number) # Create a form for the user to choose boxes from. form = filing_form(db, current_user, comic_id, 'File Comic') # Process the form. A custom validation function is used to ensure that at # least one box is selected. if form.process(onvalidation=validate_filing).accepted: # The validation was successful. Unfile the comic from all boxes, then # file it into the chosen boxes. db_access.delete_filings_for_comic(comic_id) # If only one box is selected, form.vars.boxes will be a string instead # of a list, meaning it cannot be iterated over correctly. Put it in a # list so it can. if type(form.vars.boxes) == type(''): boxes = [form.vars.boxes] else: boxes = form.vars.boxes for box_id in boxes: db_access.create_filing(comic_id, box_id) # Take the user back to the comic page. redirect(URL('comic', 'index', vars={'id': comic_id})) # If the validation fails, add an error message above the submit button. elif form.errors.error is not None: error_message = DIV( DIV( DIV('Please choose at least one box to file the comic into.', _class='error'), _class='col-md-12 text-center' ), _class='form-group' ) form.insert(-1, error_message) return dict(form=form)
def edit(): """ URLs: - /comic/edit?id=123 Function: - Display a form so the user can edit an existing comic. Notes: - If the comic does not belong to the logged in user, they will be redirected to /private/comic. """ # Find out which comic is being edited. requested_comic = request.vars.get('id') # For some reason, when the form is submitted, request.vars.id is a list # containing the same value twice. if type(requested_comic) == type([]): requested_comic = requested_comic[0] # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404. if comic is None: raise HTTP(404) # Get the id of the current user. current_user = auth.user_id # If the comic doesn't belong to the current user, redirect to the private page. if comic.owner_id != current_user: redirect(URL('private', 'index', args='comic', vars={'edit': 'true'})) # Set the title of the page. response.title = 'Edit Comic' # Create a comic editing form, passing in the ID of the comic to set the # values of the form, and to put the SQLFORM into update mode. form = comic_edit_form(db, user_id=auth.user_id, submit_button='Save Changes', edit_comic_id=comic_id) # Validate and process the form. if form.process().accepted: # Return to the comic's page. redirect(URL('comic', 'index', vars={'id': comic.id})) # If there are errors in the form, highlight the appropriate sections in red. if form.errors is not None: if len(form.errors) > 0: # Highlight the title field if it wasn't entered. if form.errors.title is not None: form[0][0]['_class'] += ' has-error' # Highlight the issue number field if that wasn't entered. if form.errors.issue_number is not None: form[0][1]['_class'] += ' has-error' # Highlight the image upload field if the image was too large. if form.errors.cover_image is not None: form[0][2]['_class'] += ' has-error' return dict(form=form)
def index(): """ URLs: - /comic?id=123 Function: - Display the details of the comic with the given ID. """ # Get the ID of the comic to display. requested_comic = request.vars.get('id') # If a malformed ID (or no ID) is passed in, throw a 404 error. try: comic_id = int(requested_comic) except ValueError as error: raise HTTP(404) # Get the details of the comic and its owner. comic = db_access.get_comic(requested_comic) # If the requested comic doesn't exist, throw a 404 error. if comic is None: raise HTTP(404) # Get the details of the comic's owner. user = db_access.get_user(comic.owner_id) # Get a list of the boxes the comic is stored in. If the comic's owner is # the currently logged in user, this can include private boxes. include_private = (comic.owner_id == user.id) boxes = db_access.get_boxes_for_comic(requested_comic, include_private=include_private) # If the comic is only filed in private boxes and the current user doesn't # own the comic, it shouldn't be visible. In this case, since the query # above would have excluded private boxes, then no boxes will have been # returned. has_permission = len(boxes) > 0 # If the user doesn't have permission, redirect to the private page. if not has_permission: redirect(URL('private', 'index', args='comic')) # Set the title of the page to show the user where they are. response.title = "{title} #{issue}".format(title=comic.title, issue=comic.issue_number) # Create a link to the comic's owner. user_link = A(user.username, _href=URL('user', 'index', vars={'id': user.id})) # Display the owner of the comic below the title. response.subtitle = 'Owned by {user}'.format(user=user_link) # The action buttons depend on whether the comic belongs to the logged-in # user. They shouldn't be able to delete or edit someone else's comic, or # copy their own comic to their collection. if comic.owner_id == auth.user_id: # Add buttons to the top of the page to edit, delete, and file the comic. page_actions = [ ('File in Boxes', URL('comic', 'file', vars={'id': comic.id}), 'credit-card'), ('Edit', URL('comic', 'edit', vars={'id': comic.id}), 'pencil'), ('Delete', URL('comic', 'confirm_delete', vars={'id': comic.id}), 'trash') ] elif auth.user_id is not None: # Add a button to copy the comic to the current user's collection, if a # user is actually logged in. page_actions = [ ('Copy to My Collection', URL('comic', 'copy', vars={'id': comic.id}), 'duplicate') ] else: page_actions = [] return dict(comic=comic, user=user, boxes=boxes, has_permission=has_permission, page_actions=page_actions)