def do_paste(request): syntax = request.POST['syntax'] if syntax == '[none]': syntax = '' elif syntax == '[auto]': lexer = pygments.lexers.guess_lexer(request.POST['content']) syntax = lexer.aliases[0] elif syntax.startswith('['): raise ValueError content = request.POST['content'] lines = content.count('\n') if content[-1] != '\n': lines += 1 paste = Paste( author=request.user, title=request.POST.get('title', ''), syntax=syntax, content=content, size=len(content), lines=lines, ) session.add(paste) session.flush() return HTTPSeeOther(location=request.route_url('pastebin.view', id=paste.id))
def new__post(request): post = BlogPost( title=request.POST['title'], content=request.POST['content'], ) session.add(post) session.flush() return HTTPSeeOther(location=request.route_url('blog.index'))
def comic_admin_folders_new_do(request): # TODO error checking... might be no POSTs, for example folder = session.query(GalleryFolder).get(request.POST['relativeto']) if not folder: # TODO raise HTTPBadRequest where = request.POST['where'] if where == 'before': # "Before" really means taking its place, so the target folder and # every subsequent folder should scoot forwards two places left = folder.left elif where == 'after': # New folder's left should immediately follow the target folder's right left = folder.right + 1 elif where == 'child': # New folder should go where its parents' current right is -- in case # there are already children, this puts the new folder last left = folder.right else: # TODO raise HTTPBadRequest # Shift any endpoints after the new left ahead by 2. This will cover both # ancestors and unrelated folders that are further along ( session.query(GalleryFolder) .filter(GalleryFolder.left >= left) .update({ GalleryFolder.left: GalleryFolder.left + 2, }, synchronize_session=False) ) ( session.query(GalleryFolder) .filter(GalleryFolder.right >= left) .update({ GalleryFolder.right: GalleryFolder.right + 2, }, synchronize_session=False) ) # Create the new folder # TODO title has to be unique, non-blank, or somethin session.add(GalleryFolder( title=request.POST['title'], left=left, right=left + 1, # TODO temporary hack until i get rid of comics entirely comic_id=folder.comic_id, )) return HTTPSeeOther( location=request.route_url('comic.admin') + '#manage-folders')
def express_love__do(request): # TODO real form handling thx source = request.user # TODO error handling lol target = session.query(User).filter_by(name=request.POST['target']).one() session.add(Love( source=source, target=target, comment=request.POST['comment'], )) return HTTPSeeOther(request.route_url('love.list'))
def permissions_grant(request): # TODO error checking, eh. is there even a flash thing yet, haha data = dict( group_id=request.POST['group'], scope=request.POST['scope'], permission=request.POST['priv'], ) existing = session.query(GroupPermission).filter_by(**data).all() if not existing: session.add(GroupPermission(**data)) return HTTPSeeOther(location=request.route_url('__core__.admin.permissions'))
def comic_admin_folders_new_do(request): # TODO error checking... might be no POSTs, for example folder = session.query(GalleryFolder).get(request.POST['relativeto']) if not folder: # TODO raise HTTPBadRequest where = request.POST['where'] if where == 'before': # "Before" really means taking its place, so the target folder and # every subsequent folder should scoot forwards two places left = folder.left elif where == 'after': # New folder's left should immediately follow the target folder's right left = folder.right + 1 elif where == 'child': # New folder should go where its parents' current right is -- in case # there are already children, this puts the new folder last left = folder.right else: # TODO raise HTTPBadRequest # Shift any endpoints after the new left ahead by 2. This will cover both # ancestors and unrelated folders that are further along (session.query(GalleryFolder).filter(GalleryFolder.left >= left).update( { GalleryFolder.left: GalleryFolder.left + 2, }, synchronize_session=False)) (session.query(GalleryFolder).filter(GalleryFolder.right >= left).update( { GalleryFolder.right: GalleryFolder.right + 2, }, synchronize_session=False)) # Create the new folder # TODO title has to be unique, non-blank, or somethin session.add( GalleryFolder( title=request.POST['title'], left=left, right=left + 1, # TODO temporary hack until i get rid of comics entirely comic_id=folder.comic_id, )) return HTTPSeeOther(location=request.route_url('comic.admin') + '#manage-folders')
def permissions_grant(request): # TODO error checking, eh. is there even a flash thing yet, haha data = dict( group_id=request.POST['group'], scope=request.POST['scope'], permission=request.POST['priv'], ) existing = session.query(GroupPermission).filter_by(**data).all() if not existing: session.add(GroupPermission(**data)) return HTTPSeeOther( location=request.route_url('__core__.admin.permissions'))
def express_love__do(request): # TODO real form handling thx source = request.user # TODO error handling lol target = session.query(User).filter_by(name=request.POST['target']).one() session.add( Love( source=source, target=target, comment=request.POST['comment'], )) return HTTPSeeOther(request.route_url('love.list'))
def comic_admin_folders_new_do(request): # TODO error checking... might be no POSTs, for example folder = session.query(GalleryFolder).get(request.POST['relativeto']) if not folder: # TODO raise HTTPBadRequest where = request.POST['where'] if where == 'before': # "Before" really means taking its place, so the target folder and # every subsequent folder should scoot forwards two places left = folder.left elif where == 'after': # New folder's left should immediately follow the target folder's right left = folder.right + 1 elif where == 'child': # Target folder needs to widen by 2, then the new folder should go just # before its right -- in case there are already children, this puts the # new folder last folder.right += 2 session.flush() left = folder.right - 2 else: # TODO raise HTTPBadRequest # Push everyone else forwards by 2 ( session.query(GalleryFolder) .filter(GalleryFolder.left >= left) .update({ GalleryFolder.left: GalleryFolder.left + 2, GalleryFolder.right: GalleryFolder.right + 2, }, synchronize_session=False) ) # Create the new folder # TODO title has to be unique, non-blank, or somethin session.add(GalleryFolder( title=request.POST['title'], left=left, right=left + 1, # TODO temporary hack until i get rid of comics entirely comic_id=folder.comic_id, )) return HTTPSeeOther( location=request.route_url('comic.admin') + '#manage-folders')
def create_user(parser, args): engine = engine_from_config(vars(args), 'sqlalchemy.') session.configure(bind=engine) with transaction.manager: all_groups = { group.name: group for group in session.query(Group) } username = input('username: '******'email: ').strip() password = getpass.getpass('password: '******'confirm password: '******'t match!") sys.exit(1) group_names = [] if all_groups: print() print("available groups: {}".format(', '.join(all_groups))) group_names = input('comma-separated list of groups to add to: ').strip().split(',') with transaction.manager: pwhash = bcrypt.hashpw( password.encode('utf8'), bcrypt.gensalt(14), ).decode('ascii') # TODO would be neat to have a password field that hashes on assignment # and does the right thing with equality check user = User(name=username, email=email, password=pwhash, groups=[]) for group_name in group_names: user.groups.append(all_groups[group_name]) session.add(user) session.flush() userid = user.id print() print("created user {} with id {}".format(username, userid))
def register__do(request): # TODO finish this raise HTTPForbidden # TODO check for duplicate username haha. # TODO and er duplicate email, which is less likely to happen i suppose user = User( email=request.session['pending_auth']['persona_email'], name=request.POST['username'], ) session.add(user) session.flush() url = request.session['pending_auth']['return_to'] # TODO this is the sort of thing that should only happen if the transaction # succeeds otherwise! del request.session['pending_auth'] return HTTPSeeOther( location=url, headers=remember(request, user), )
def init_db(parser, args): settings = vars(args) # Logging # TODO this should probably go in the main entry point coloredlogs.install(level=logging.INFO) # TODO what is this for, it was debug-only, is there any reason we wouldn't want it #logging.basicConfig() #logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) # Plugin loading plugin_list = import_plugins(settings.get('spline.plugins', ())) engine = engine_from_config(settings, 'sqlalchemy.') session.configure(bind=engine) Base.metadata.create_all(engine, checkfirst=True) comic_title = settings.get('spline.comic_name') chapter_title = settings.get('spline.chapter_name') with transaction.manager: try: g = session.query(Group).filter_by(id=1).one() except: g = Group(id=1, name='admin') session.add(g) try: gp0 = session.query(GroupPermission).filter_by(id=1).one() except: gp0 = GroupPermission(id=1, scope='core', permission='admin') gp0.group = g session.add(gp0) # Only needed if the comic plugin is loaded if 'spline_comic' in plugin_list: from spline_comic.models import Comic, ComicChapter try: gp1 = session.query(GroupPermission).filter_by(id=1).one() except: gp1 = GroupPermission(id=1, scope='comic', permission='admin') gp1.group = g session.add(gp1) try: comic = session.query(Comic).filter_by(id=1).one() except: comic = Comic(id=1, title=comic_title, config_timezone='GMT') session.add(comic) try: chap = session.query(ComicChapter).filter_by(id=1).one() except: chap = ComicChapter(id=1, title=chapter_title, left=0, right=0) chap.comic = comic session.add(chap) # Only needed if the wiki is loaded if 'spline_wiki' in plugin_list: try: gp2 = session.query(GroupPermission).filter_by(id=2).one() except: gp2 = GroupPermission(id=2, scope='wiki', permission='edit') gp2.group = g session.add(gp2)
def comic_upload_do(request): # TODO validation and all that boring stuff file_upload = request.POST['file'] fh = file_upload.file from spline.feature.filestore import IStorage storage = request.registry.queryUtility(IStorage) _, ext = os.path.splitext(file_upload.filename) filename = storage.store(fh, ext) # TODO ha ha this is stupid # TODO very skinny images shouldn't be blindly made 200x200 fh.seek(0) thumb = subprocess.check_output( ['convert', '-', '-resize', '200x200', '-'], stdin=fh) # TODO this interface is bad also thumbname = storage.store(BytesIO(thumb), ext) # TODO wire into transaction so the file gets deleted on rollback last_chapter = (session.query(ComicChapter).filter( ComicChapter.id == int(request.POST['chapter'])).one()) when = request.POST['when'] if when == 'now': date_published = datetime.now(pytz.utc) elif when == 'queue': last_queued, queue_next_date = _get_last_queued_date() date_published = datetime.combine( queue_next_date, time(tzinfo=XXX_HARDCODED_TIMEZONE), ) date_published = date_published.astimezone(pytz.utc) # Fetch next page number and ordering. Also need to shift everyone else # forwards by one if this is bumping the queue. Blurgh. max_order, = (session.query(func.max(ComicPage.order)).filter( ComicPage.date_published <= date_published).first()) if max_order is None: max_order = 0 next_order = max_order + 1 (session.query(ComicPage).filter(ComicPage.order >= next_order).update( {ComicPage.order: ComicPage.order + 1})) max_page_number, = (session.query(func.max( ComicPage.page_number)).with_parent(last_chapter).filter( ComicPage.date_published <= date_published).first()) if max_page_number is None: max_page_number = 0 next_page_number = max_page_number + 1 (session.query(ComicPage).with_parent(last_chapter).filter( ComicPage.page_number >= next_page_number).update( {ComicPage.page_number: ComicPage.page_number + 1})) page = ComicPage( chapter=last_chapter, author=request.user, date_published=date_published, timezone=XXX_HARDCODED_TIMEZONE.zone, order=next_order, page_number=next_page_number, # TODO more validation here too title=request.POST['title'], comment=request.POST['comment'], media=[ GalleryMedia_Image( image_file=os.path.basename(filename), thumbnail_file=os.path.basename(thumbname), ) ], ) if request.POST.get('iframe_url'): url = request.POST['iframe_url'] # If it's a YouTube URL, convert to the embed URL automatically # TODO this seems like a neat thing to do for many other services and # make a tiny library out of, if it's not done already? # TODO why doesn't this use urlparse??? m = re.match( '^(?:https?://)?(?:www[.])?youtube[.]com/watch[?]v=([-_0-9a-zA-Z]+)(?:&|$)', url) if m: url = "https://www.youtube.com/embed/{}?rel=0".format(m.group(1)) m = re.match('^(?:https?://)?youtu[.]be/([-_0-9a-zA-Z]+)(?:[?]|$)', url) if m: url = "https://www.youtube.com/embed/{}?rel=0".format(m.group(1)) try: width = int(request.POST['iframe_width']) except (KeyError, ValueError): width = 800 try: height = int(request.POST['iframe_height']) except (KeyError, ValueError): height = 600 page.media.append( GalleryMedia_IFrame(url=url, width=width, height=height)) session.add(page) session.flush() return HTTPSeeOther(location=request.resource_url(page))
def initdb(**settings): engine = engine_from_config(settings, 'sqlalchemy.') session.configure(bind=engine) config = Configurator(settings=settings) # Logging config.include('spline.lib.logging') # Plugin loading debug = settings.get('spline.debug') if debug: logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) plugin_list = [] try: for plugins in settings.get('spline.plugins', ()): plugin, route_prefix = plugins.split(':', 1) importlib.import_module(plugin) plugin_list.append(plugin) except TypeError: pass Base.metadata.create_all(engine, checkfirst=True) adm_name = settings.get('spline.admin_name') adm_pw = settings.get('spline.admin_pw') adm_email = settings.get('spline.admin_email') comic_title = settings.get('spline.comic_name') chapter_title = settings.get('spline.chapter_name') p = adm_pw.encode('utf8') pw = hashpw(p, gensalt(14)) with transaction.manager: try: u = session.query(User).filter_by(id=1).one() except: u = User(id=1, email=adm_email, name=adm_name, password=pw.decode('ascii')) session.add(u) try: g = session.query(Group).filter_by(id=1).one() except: g = Group(id=1, name='admin') g.users.append(u) session.add(g) try: gp0 = session.query(GroupPermission).filter_by(id=1).one() except: gp0 = GroupPermission(id=1, scope='core', permission='admin') gp0.group = g session.add(gp0) # Only needed if the comic plugin is loaded if 'spline_comic' in plugin_list: from spline_comic.models import Comic, ComicChapter try: gp1 = session.query(GroupPermission).filter_by(id=1).one() except: gp1 = GroupPermission(id=1, scope='comic', permission='admin') gp1.group = g session.add(gp1) try: comic = session.query(Comic).filter_by(id=1).one() except: comic = Comic(id=1, title=comic_title, config_timezone='GMT') session.add(comic) try: chap = session.query(ComicChapter).filter_by(id=1).one() except: chap = ComicChapter(id=1, title=chapter_title, left=0, right=0) chap.comic = comic session.add(chap) # Only needed if the wiki is loaded if 'spline_wiki' in plugin_list: try: gp2 = session.query(GroupPermission).filter_by(id=2).one() except: gp2 = GroupPermission(id=2, scope='wiki', permission='edit') gp2.group = g session.add(gp2)
def comic_upload_do(request): # TODO validation and all that boring stuff file_upload = request.POST['file'] fh = file_upload.file from spline.feature.filestore import IStorage storage = request.registry.queryUtility(IStorage) _, ext = os.path.splitext(file_upload.filename) filename = storage.store(fh, ext) # TODO ha ha this is stupid # TODO very skinny images shouldn't be blindly made 200x200 fh.seek(0) thumb = subprocess.check_output(['convert', '-', '-resize', '200x200', '-'], stdin=fh) # TODO this interface is bad also thumbname = storage.store(BytesIO(thumb), ext) # TODO wire into transaction so the file gets deleted on rollback last_chapter = ( session.query(ComicChapter) .filter(ComicChapter.id == int(request.POST['chapter'])) .one() ) when = request.POST['when'] if when == 'now': date_published = datetime.now(pytz.utc) elif when == 'queue': last_queued, queue_next_date = _get_last_queued_date() date_published = datetime.combine( queue_next_date, time(tzinfo=XXX_HARDCODED_TIMEZONE), ) date_published = date_published.astimezone(pytz.utc) # Fetch next page number and ordering. Also need to shift everyone else # forwards by one if this is bumping the queue. Blurgh. max_order, = ( session.query(func.max(ComicPage.order)) .filter(ComicPage.date_published <= date_published) .first() ) if max_order is None: max_order = 0 next_order = max_order + 1 ( session.query(ComicPage) .filter(ComicPage.order >= next_order) .update({ComicPage.order: ComicPage.order + 1}) ) max_page_number, = ( session.query(func.max(ComicPage.page_number)) .with_parent(last_chapter) .filter(ComicPage.date_published <= date_published) .first() ) if max_page_number is None: max_page_number = 0 next_page_number = max_page_number + 1 ( session.query(ComicPage) .with_parent(last_chapter) .filter(ComicPage.page_number >= next_page_number) .update({ComicPage.page_number: ComicPage.page_number + 1}) ) page = ComicPage( chapter=last_chapter, author=request.user, date_published=date_published, timezone=XXX_HARDCODED_TIMEZONE.zone, order=next_order, page_number=next_page_number, # TODO more validation here too title=request.POST['title'], comment=request.POST['comment'], media=[ GalleryMedia_Image( image_file=os.path.basename(filename), thumbnail_file=os.path.basename(thumbname), ) ], ) if request.POST.get('iframe_url'): url = request.POST['iframe_url'] # If it's a YouTube URL, convert to the embed URL automatically # TODO this seems like a neat thing to do for many other services and # make a tiny library out of, if it's not done already? # TODO why doesn't this use urlparse??? m = re.match( '^(?:https?://)?(?:www[.])?youtube[.]com/watch[?]v=([-_0-9a-zA-Z]+)(?:&|$)', url) if m: url = "https://www.youtube.com/embed/{}?rel=0".format(m.group(1)) m = re.match('^(?:https?://)?youtu[.]be/([-_0-9a-zA-Z]+)(?:[?]|$)', url) if m: url = "https://www.youtube.com/embed/{}?rel=0".format(m.group(1)) try: width = int(request.POST['iframe_width']) except (KeyError, ValueError): width = 800 try: height = int(request.POST['iframe_height']) except (KeyError, ValueError): height = 600 page.media.append(GalleryMedia_IFrame( url=url, width=width, height=height)) session.add(page) session.flush() return HTTPSeeOther(location=request.resource_url(page))