Esempio n. 1
0
def follow(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if any(m.id == mod.id for m in current_user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = 1
        event.events = 1
        db.add(event)
        db.flush()
        db.commit()
        mod.follow_events.append(event)
    else:
        event.delta += 1
        event.events += 1
    mod.follower_count += 1
    current_user.following.append(mod)
    return {"success": True}
Esempio n. 2
0
def unfollow(mod_id):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not any(m.id == mod.id for m in user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = -1
        event.events = 1
        mod.follow_events.append(event)
        db.add(event)
    else:
        event.delta -= 1
        event.events += 1
    mod.follower_count -= 1
    user.following = [m for m in user.following if m.id == mod_id]
    db.commit()
    return {"success": True}
Esempio n. 3
0
def feature(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    game = Game.query.filter(Game.id == mod.game_id).first()
    session['game'] = game.id;
    session['gamename'] = game.name;
    session['gameshort'] = game.short;
    session['gameid'] = game.id;
    if not mod or not game:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(desc(Game.id)).first()
        session['game'] = ga.id;
        session['gamename'] = ga.name;
        session['gameshort'] = ga.short;
        session['gameid'] = ga.id;
        abort(404)
    else:
        session['game'] = game.id;
        session['gamename'] = game.name;
        session['gameshort'] = game.short;
        session['gameid'] = game.id;
    if any(Featured.query.filter(Featured.mod_id == mod_id).all()):
        abort(409)
    feature = Featured()
    feature.mod = mod
    db.add(feature)
    return { "success": True }
Esempio n. 4
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not current_user or current_user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \
            ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\
            .order_by(desc(DownloadEvent.created))\
            .first()
    if not os.path.isfile(os.path.join(_cfg('storage'), version.download_path)):
        abort(404)
    # Events are aggregated hourly
    if not download or ((datetime.now() - download.created).seconds / 60 / 60) >= 1:
        download = DownloadEvent()
        download.mod = mod
        download.version = version
        download.downloads = 1
        mod.downloads.append(download)
        db.add(download)
    else:
        download.downloads += 1
    mod.download_count += 1
    return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True)
Esempio n. 5
0
def register_with_oauth_authorized():
    '''
    This endpoint should be called after authorizing with oauth, by the user.
    '''
    email = request.form.get('email')
    username = request.form.get('username')
    provider = request.form.get('provider')
    remote_user = request.form.get('remote_user')

    good = True
    if check_username_for_registration(username):
        good = False
    if check_email_for_registration(email):
        good = False

    if good:
        password = binascii.b2a_hex(os.urandom(99))
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.flush()  # to get an ID.
        auth = UserAuth(user.id, remote_user, provider)
        db.add(auth)
        db.commit()  # Commit before trying to email

        send_confirmation(user)
        return redirect("/account-pending")

    return render_register_with_oauth(provider, remote_user, username, email)
Esempio n. 6
0
def unfollow(mod_id):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not any(m.id == mod.id for m in user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = -1
        event.events = 1
        mod.follow_events.append(event)
        db.add(event)
    else:
        event.delta -= 1
        event.events += 1
    mod.follower_count -= 1
    user.following = [m for m in user.following if m.id == mod_id]
    db.commit()
    return { "success": True }
Esempio n. 7
0
def feature(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    game = Game.query.filter(Game.id == mod.game_id).first()
    session['game'] = game.id
    session['gamename'] = game.name
    session['gameshort'] = game.short
    session['gameid'] = game.id
    if not mod or not game:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(
            desc(Game.id)).first()
        session['game'] = ga.id
        session['gamename'] = ga.name
        session['gameshort'] = ga.short
        session['gameid'] = ga.id
        abort(404)
    else:
        session['game'] = game.id
        session['gamename'] = game.name
        session['gameshort'] = game.short
        session['gameid'] = game.id
    if any(Featured.query.filter(Featured.mod_id == mod_id).all()):
        abort(409)
    feature = Featured()
    feature.mod = mod
    db.add(feature)
    return {"success": True}
Esempio n. 8
0
def download(mod_id, mod_name, version):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not user or user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \
            ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\
            .order_by(desc(DownloadEvent.created))\
            .first()
    # Events are aggregated hourly
    if not download or ((datetime.now() - download.created).seconds / 60 / 60) >= 1:
        download = DownloadEvent()
        download.mod = mod
        download.version = version
        download.downloads = 1
        mod.downloads.append(download)
        db.add(download)
    else:
        download.downloads += 1
    mod.download_count += 1
    db.commit()
    return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True)
Esempio n. 9
0
def register_with_oauth_authorized():
    '''
    This endpoint should be called after authorizing with oauth, by the user.
    '''
    email = request.form.get('email')
    username = request.form.get('username')
    provider = request.form.get('provider')
    remote_user = request.form.get('remote_user')

    good = True
    if check_username_for_registration(username):
        good = False
    if check_email_for_registration(email):
        good = False

    if good:
        password = binascii.b2a_hex(os.urandom(99))
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.flush()  # to get an ID.
        auth = UserAuth(user.id, remote_user, provider)
        db.add(auth)
        db.commit()  # Commit before trying to email

        send_confirmation(user)
        return redirect("/account-pending")

    return render_register_with_oauth(provider, remote_user, username, email)
Esempio n. 10
0
def follow(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if any(m.id == mod.id for m in current_user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = 1
        event.events = 1
        db.add(event)
        db.flush()
        db.commit()
        mod.follow_events.append(event)
    else:
        event.delta += 1
        event.events += 1
    mod.follower_count += 1
    current_user.following.append(mod)
    return { "success": True }
Esempio n. 11
0
def edit_media(mod_id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not editable:
        abort(401)
    screenshots = request.form.get('screenshots')
    videos = request.form.get('videos')
    background = request.form.get('backgroundMedia')
    bgOffsetX = request.form.get('bg-offset-x')
    bgOffsetY = request.form.get('bg-offset-y')
    screenshot_list = screenshots.split(',')
    video_list = videos.split(',')
    if len(screenshot_list) > 5 \
        or len(video_list) > 2 \
        or len(background) > 32:
        abort(400)
    [db.delete(m) for m in mod.media]
    for screenshot in screenshot_list:
        if screenshot:
            r = requests.get('https://mediacru.sh/' + screenshot + '.json')
            if r.status_code != 200:
                abort(400)
            j = r.json()
            data = ''
            if j['blob_type'] == 'image':
                for f in j['files']:
                    if f['type'] == 'image/jpeg' or f['type'] == 'image/png':
                        data = f['file']
            else:
                abort(400)
            m = Media(j['hash'], j['blob_type'], data)
            mod.medias.append(m)
    for video in video_list:
        if video:
            r = requests.get('https://mediacru.sh/' + video + '.json')
            if r.status_code != 200:
                abort(400)
            j = r.json()
            data = ''
            if j['blob_type'] == 'video':
                data = j['hash']
            else:
                abort(400)
            m = Media(j['hash'], j['blob_type'], data)
            mod.medias.append(m)
            db.add(m)
    mod.background = background
    try:
        mod.bgOffsetX = int(bgOffsetX)
        mod.bgOffsetY = int(bgOffsetY)
    except:
        pass # Do not modify background in this case
    return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
Esempio n. 12
0
def register():
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        followMod = request.form.get('follow-mod')
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')
        if not email:
            kwargs['emailError'] = 'Email is required.'
        else:
            if not re.match(r"^[^@]+@[^@]+\.[^@]+$", email):
                kwargs['emailError'] = 'Please specify a valid email address.'
            elif db.query(User).filter(User.email == email).first():
                kwargs['emailError'] = 'A user with this email already exists.'
        if not username:
            kwargs['usernameError'] = 'Username is required.'
        else:
            if not re.match(r"^[A-Za-z0-9_]+$", username):
                kwargs[
                    'usernameError'] = 'Please only use letters, numbers, and underscores.'
            if len(username) < 3 or len(username) > 24:
                kwargs[
                    'usernameError'] = 'Usernames must be between 3 and 24 characters.'
            if db.query(User).filter(User.username.ilike(username)).first():
                kwargs['usernameError'] = 'A user by this name already exists.'
        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs[
                    'passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs[
                    'passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit(
        )  # We do this manually so that we're sure everything's hunky dory before the email leaves
        if followMod:
            send_confirmation(user, followMod)
        else:
            send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html")
Esempio n. 13
0
def post_blog():
    title = request.form.get('post-title')
    body = request.form.get('post-body')
    post = BlogPost()
    post.title = title
    post.text = body
    db.add(post)
    db.commit()
    return redirect("/blog/" + str(post.id))
Esempio n. 14
0
def post_blog():
    title = request.form.get('post-title')
    body = request.form.get('post-body')
    post = BlogPost()
    post.title = title
    post.text = body
    db.add(post)
    db.commit()
    return redirect("/blog/" + str(post.id))
Esempio n. 15
0
def create_publisher():
    name = request.form.get("pname")
    if not name:
        return redirect("/asdf")
    if any(Publisher.query.filter(Publisher.name == name)):
        return redirect("/fsda")
    gname = Publisher(name)
    db.add(gname)
    db.commit()
    return redirect("/admin")
Esempio n. 16
0
def feature(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if any(Featured.query.filter(Featured.mod_id == mod_id).all()):
        abort(409)
    feature = Featured()
    feature.mod = mod
    db.add(feature)
    return { "success": True }
Esempio n. 17
0
def feature(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if any(Featured.query.filter(Featured.mod_id == mod_id).all()):
        abort(409)
    feature = Featured()
    feature.mod = mod
    db.add(feature)
    return { "success": True }
Esempio n. 18
0
def create_version():
    friendly = request.form.get("friendly_version")
    if not friendly:
        return redirect("/asdf")
    if any(GameVersion.query.filter(GameVersion.friendly_version == friendly)):
        return redirect("/fsda")
    version = GameVersion(friendly)
    db.add(version)
    db.commit()
    return redirect("/admin")
Esempio n. 19
0
def create_version():
    friendly = request.form.get("friendly_version")
    if not friendly:
        return redirect("/asdf")
    if any(GameVersion.query.filter(GameVersion.friendly_version == friendly)):
        return redirect("/fsda")
    version = GameVersion(friendly)
    db.add(version)
    db.commit()
    return redirect("/admin")
Esempio n. 20
0
def edit_list(list_id, list_name):
    mod_list = ModList.query.filter(ModList.id == list_id).first()
    if not mod_list:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod_list.user_id:
            editable = True
    if not editable:
        abort(401)
    if request.method == 'GET':
        return render_template(
            "edit_list.html", **{
                'mod_list': mod_list,
                'mod_ids': [m.mod.id for m in mod_list.mods],
                "site_name": _cfg('site-name'),
                "support_mail": _cfg('support-mail')
            })
    else:
        description = request.form.get('description')
        background = request.form.get('background')
        bgOffsetY = request.form.get('bg-offset-y')
        mods = json.loads(request.form.get('mods'))
        mod_list.description = description
        if background and background != '':
            mod_list.background = background
        try:
            mod_list.bgOffsetY = int(bgOffsetY)
        except:
            pass
        # Remove mods
        removed_mods = [m for m in mod_list.mods if not m.mod_id in mods]
        for mod in removed_mods:
            mod_list.mods.remove(mod)

        # Add mods
        added_mods = [
            m for m in mods if not m in [mod.mod.id for mod in mod_list.mods]
        ]
        for m in added_mods:
            mod = Mod.query.filter(Mod.id == m).first()
            mli = ModListItem()
            mli.mod_id = mod.id
            mli.mod_list = mod_list
            mod_list.mods.append(mli)
            db.add(mli)
            db.commit()
        for mod in mod_list.mods:
            mod.sort_index = mods.index(mod.mod.id)
        return redirect(
            url_for("lists.view_list",
                    list_id=mod_list.id,
                    list_name=mod_list.name))
Esempio n. 21
0
def register():
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        followMod = request.form.get('follow-mod')
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')
        if not email:
            kwargs['emailError'] = 'Email is required.'
        else:
            if not re.match(r"^[^@]+@[^@]+\.[^@]+$", email):
                kwargs['emailError'] = 'Please specify a valid email address.'
            elif db.query(User).filter(User.email == email).first():
                kwargs['emailError'] = 'A user with this email already exists.'
            elif _mailbans.isMailBanned(email):
                kwargs['emailError'] = 'This email host is banned, please use an alternative, this is to prevent botting, sorry.'
        if not username:
            kwargs['usernameError'] = 'Username is required.'
        else:
            if not re.match(r"^[A-Za-z0-9_]+$", username):
                kwargs['usernameError'] = 'Please only use letters, numbers, and underscores.'
            if len(username) < 3 or len(username) > 24:
                kwargs['usernameError'] = 'Usernames must be between 3 and 24 characters.'
            if db.query(User).filter(User.username.ilike(username)).first():
                kwargs['usernameError'] = 'A user by this name already exists.'
        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs['passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs['passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit() # We do this manually so that we're sure everything's hunky dory before the email leaves
        if followMod:
            send_confirmation(user, followMod)
        else:
            send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html")
Esempio n. 22
0
def edit_media(mod_id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not editable:
        abort(401)
    screenshots = request.form.get('screenshots')
    videos = request.form.get('videos')
    background = request.form.get('backgroundMedia')
    screenshot_list = screenshots.split(',')
    video_list = videos.split(',')
    if len(screenshot_list) > 5 \
        or len(video_list) > 2 \
        or len(background) > 32:
        abort(400)
    [db.delete(m) for m in mod.media]
    for screenshot in screenshot_list:
        if screenshot:
            r = requests.get('https://mediacru.sh/' + screenshot + '.json')
            if r.status_code != 200:
                abort(400)
            j = r.json()
            data = ''
            if j['blob_type'] == 'image':
                for f in j['files']:
                    if f['type'] == 'image/jpeg' or f['type'] == 'image/png':
                        data = f['file']
            else:
                abort(400)
            m = Media(j['hash'], j['blob_type'], data)
            mod.medias.append(m)
    for video in video_list:
        if video:
            r = requests.get('https://mediacru.sh/' + video + '.json')
            if r.status_code != 200:
                abort(400)
            j = r.json()
            data = ''
            if j['blob_type'] == 'video':
                data = j['hash']
            else:
                abort(400)
            m = Media(j['hash'], j['blob_type'], data)
            mod.medias.append(m)
            db.add(m)
    mod.background = background
    db.commit()
    return redirect('/mod/' + str(mod.id) + '/' +
                    secure_filename(mod.name)[:64])
Esempio n. 23
0
def register():
    if not _cfgb('registration'):
        return redirect("/")
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        followMod = request.form.get('follow-mod')
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')



        error = check_email_for_registration(email)
        if error:
            kwargs['emailError'] = error

        error = check_username_for_registration(username)
        if error:
            kwargs['usernameError'] = error

        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs['passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs['passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            # Fill in config values
            kwargs['site_name'] = _cfg('site-name')
            kwargs['support_mail'] = _cfg('support-mail')
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            kwargs['registration'] = registration = _cfgb('registration')
            print("test")
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit() # We do this manually so that we're sure everything's hunky dory before the email leaves
        if followMod:
            send_confirmation(user, followMod)
        else:
            send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html", **{ "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail'), "registration": _cfgb('registration') })
Esempio n. 24
0
def register():
    if not _cfgb('registration'):
        return redirect("/")
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        followMod = request.form.get('follow-mod')
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')

        error = check_email_for_registration(email)
        if error:
            kwargs['emailError'] = error

        error = check_username_for_registration(username)
        if error:
            kwargs['usernameError'] = error

        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs[
                    'passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs[
                    'passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            kwargs['registration'] = registration = _cfgb('registration')
            print("test")
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit(
        )  # We do this manually so that we're sure everything's hunky dory before the email leaves
        if followMod:
            send_confirmation(user, followMod)
        else:
            send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html",
                               registration=_cfgb('registration'))
Esempio n. 25
0
def update(mod_id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not editable:
        abort(401)
    version = request.form.get('version')
    changelog = request.form.get('changelog')
    ksp_version = request.form.get('ksp-version')
    notify = request.form.get('notify-followers')
    zipball = request.files.get('zipball')
    if not version \
        or not ksp_version \
        or not zipball:
        # Client side validation means that they're just being pricks if they
        # get here, so we don't need to show them a pretty error message
        abort(400)
    if notify == None:
        notify = False
    else:
        notify = notify.lower() == "on"
    filename = secure_filename(mod.name) + '-' + secure_filename(version) + '.zip'
    base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name))
    full_path = os.path.join(_cfg('storage'), base_path)
    if not os.path.exists(full_path):
        os.makedirs(full_path)
    path = os.path.join(full_path, filename)
    if os.path.isfile(path):
        # We already have this version
        # TODO: Error message
        abort(400)
    zipball.save(path)
    if not zipfile.is_zipfile(path):
        os.remove(path)
        abort(400) # TODO: Error message
    version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename))
    version.changelog = changelog
    # Assign a sort index
    version.sort_index = max([v.sort_index for v in mod.versions]) + 1
    mod.versions.append(version)
    if notify:
        send_update_notification(mod)
    db.add(version)
    db.commit()
    mod.default_version_id = version.id
    return redirect('/mod/' + mod_id + '/' + secure_filename(mod.name))
Esempio n. 26
0
def create_game():
    name = request.form.get("gname")
    sname = request.form.get("sname")
    pid = request.form.get("pname")
    if not name or not pid or not sname:
        return redirect("/asdf")
    if any(Game.query.filter(Game.name == name)):
        return redirect("/fsda")

    go = Game(name,pid,sname)
    db.add(go)
    db.commit()
    return redirect("/admin")
Esempio n. 27
0
def update(mod_id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not editable:
        abort(401)
    if request.method == 'GET':
        return render_template("update.html", **{'mod': mod})
    else:
        version = request.form.get('version')
        changelog = request.form.get('changelog')
        ksp_version = request.form.get('ksp-version')
        zipball = request.files.get('zipball')
        if not version \
            or not ksp_version \
            or not zipball:
            # Client side validation means that they're just being pricks if they
            # get here, so we don't need to show them a pretty error message
            abort(400)
        filename = secure_filename(
            mod.name) + '-' + secure_filename(version) + '.zip'
        base_path = os.path.join(
            secure_filename(user.username) + '_' + str(user.id),
            secure_filename(mod.name))
        full_path = os.path.join(_cfg('storage'), base_path)
        if not os.path.exists(full_path):
            os.makedirs(full_path)
        path = os.path.join(full_path, filename)
        if os.path.isfile(path):
            # We already have this version
            # TODO: Error message
            abort(400)
        zipball.save(path)
        if not zipfile.is_zipfile(path):
            os.remove(path)
            abort(400)  # TODO: Error message
        version = ModVersion(secure_filename(version), ksp_version,
                             os.path.join(base_path, filename))
        version.changelog = changelog
        mod.versions.append(version)
        send_update_notification(mod)
        db.add(version)
        db.commit()
        return redirect('/mod/' + mod_id + '/' + secure_filename(mod.name))
Esempio n. 28
0
def edit_list(list_id, list_name):
    mod_list = ModList.query.filter(ModList.id == list_id).first()
    ga = Game.query.filter(Game.id == mod_list.game_id).first()
    if not mod_list:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod_list.user_id:
            editable = True
    if not editable:
        abort(401)
    if request.method == 'GET':
        return render_template("edit_list.html",
            **{
                'mod_list': mod_list,
                'mod_ids': [m.mod.id for m in mod_list.mods],
                'ga': ga
            })
    else:
        description = request.form.get('description')
        background = request.form.get('background')
        bgOffsetY = request.form.get('bg-offset-y')
        mods = json.loads(request.form.get('mods'))
        mod_list.description = description
        if background and background != '':
            mod_list.background = background
        try:
            mod_list.bgOffsetY = int(bgOffsetY)
        except:
            pass
        # Remove mods
        removed_mods = [m for m in mod_list.mods if not m.mod_id in mods]
        for mod in removed_mods:
            mod_list.mods.remove(mod)

        # Add mods
        added_mods = [m for m in mods if not m in [mod.mod.id for mod in mod_list.mods]]
        for m in added_mods:
            mod = Mod.query.filter(Mod.id == m).first()
            mli = ModListItem()
            mli.mod_id = mod.id
            mli.mod_list = mod_list
            mod_list.mods.append(mli)
            db.add(mli)
            db.commit()
        for mod in mod_list.mods:
            mod.sort_index = mods.index(mod.mod.id)
        return redirect(url_for("lists.view_list", list_id=mod_list.id, list_name=mod_list.name))
Esempio n. 29
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not current_user or current_user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \
            ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\
            .order_by(desc(DownloadEvent.created))\
            .first()
    if not os.path.isfile(os.path.join(_cfg('storage'), version.download_path)):
        abort(404)
    
    if not 'Range' in request.headers:
        # Events are aggregated hourly
        if not download or ((datetime.now() - download.created).seconds / 60 / 60) >= 1:
            download = DownloadEvent()
            download.mod = mod
            download.version = version
            download.downloads = 1
            db.add(download)
            db.flush()
            db.commit()
            mod.downloads.append(download)
        else:
            download.downloads += 1
        mod.download_count += 1
    
    if _cfg("cdn-domain"):
        return redirect("http://" + _cfg("cdn-domain") + '/' + version.download_path, code=302)
    
    response = None
    if _cfg("use-x-accel") == 'nginx':
        response = make_response("")
        response.headers['Content-Type'] = 'application/zip'
        response.headers['Content-Disposition'] = 'attachment; filename=' + os.path.basename(version.download_path)
        response.headers['X-Accel-Redirect'] = '/internal/' + version.download_path
    if _cfg("use-x-accel") == 'apache':
        response = make_response("")
        response.headers['Content-Type'] = 'application/zip'
        response.headers['Content-Disposition'] = 'attachment; filename=' + os.path.basename(version.download_path)
        response.headers['X-Sendfile'] = os.path.join(_cfg('storage'), version.download_path)
    if response is None:
        response = make_response(send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True))
    return response
Esempio n. 30
0
def register():
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')
        if not email:
            kwargs['emailError'] = 'Email is required.'
        else:
            if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
                kwargs['emailError'] = 'Please specify a valid email address.'
            elif db.query(User).filter(User.email == email).first():
                kwargs['emailError'] = 'A user with this email already exists.'
        if not username:
            kwargs['usernameError'] = 'Username is required.'
        else:
            if not re.match(r"[A-Za-z0-9_]+", username):
                kwargs['usernameError'] = 'Please only use letters, numbers, and underscores.'
            if len(username) < 3 or len(username) > 12:
                kwargs['usernameError'] = 'Usernames must be between 3 and 12 characters.'
            if db.query(User).filter(User.username == username).first():
                kwargs['usernameError'] = 'A user by this name already exists.'
        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs['passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs['passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit()
        send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html")
Esempio n. 31
0
def update(mod_id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not editable:
        abort(401)
    if request.method == 'GET':
        return render_template("update.html", **{ 'mod': mod })
    else:
        version = request.form.get('version')
        changelog = request.form.get('changelog')
        ksp_version = request.form.get('ksp-version')
        zipball = request.files.get('zipball')
        if not version \
            or not ksp_version \
            or not zipball:
            # Client side validation means that they're just being pricks if they
            # get here, so we don't need to show them a pretty error message
            abort(400)
        filename = secure_filename(mod.name) + '-' + secure_filename(version) + '.zip'
        base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name))
        full_path = os.path.join(_cfg('storage'), base_path)
        if not os.path.exists(full_path):
            os.makedirs(full_path)
        path = os.path.join(full_path, filename)
        if os.path.isfile(path):
            # We already have this version
            # TODO: Error message
            abort(400)
        zipball.save(path)
        if not zipfile.is_zipfile(path):
            os.remove(path)
            abort(400) # TODO: Error message
        version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename))
        version.changelog = changelog
        mod.versions.append(version)
        send_update_notification(mod)
        db.add(version)
        db.commit()
        return redirect('/mod/' + mod_id + '/' + secure_filename(mod.name))
Esempio n. 32
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not current_user
                              or current_user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \
            ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\
            .order_by(desc(DownloadEvent.created))\
            .first()
    if not os.path.isfile(os.path.join(_cfg('storage'),
                                       version.download_path)):
        abort(404)

    if not 'Range' in request.headers:
        # Events are aggregated hourly
        if not download or (
            (datetime.now() - download.created).seconds / 60 / 60) >= 1:
            download = DownloadEvent()
            download.mod = mod
            download.version = version
            download.downloads = 1
            db.add(download)
            db.flush()
            db.commit()
            mod.downloads.append(download)
        else:
            download.downloads += 1
        mod.download_count += 1

    response = make_response(
        send_file(os.path.join(_cfg('storage'), version.download_path),
                  as_attachment=True))
    if _cfg("use-x-accel") == 'true':
        response = make_response("")
        response.headers['Content-Type'] = 'application/zip'
        response.headers[
            'Content-Disposition'] = 'attachment; filename=' + os.path.basename(
                version.download_path)
        response.headers[
            'X-Accel-Redirect'] = '/internal/' + version.download_path
    return response
Esempio n. 33
0
def unfollow(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    game = Game.query.filter(Game.id == mod.game_id).first()
    session['game'] = game.id
    session['gamename'] = game.name
    session['gameshort'] = game.short
    session['gameid'] = game.id
    if not mod or not game:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(
            desc(Game.id)).first()
        session['game'] = ga.id
        session['gamename'] = ga.name
        session['gameshort'] = ga.short
        session['gameid'] = ga.id
        abort(404)
    else:
        session['game'] = game.id
        session['gamename'] = game.name
        session['gameshort'] = game.short
        session['gameid'] = game.id
    if not any(m.id == mod.id for m in current_user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = -1
        event.events = 1
        mod.follow_events.append(event)
        db.add(event)
    else:
        event.delta -= 1
        event.events += 1
    mod.follower_count -= 1
    current_user.following = [
        m for m in current_user.following if m.id != int(mod_id)
    ]
    return {"success": True}
Esempio n. 34
0
def follow(mod_id):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    game = Game.query.filter(Game.id == mod.game_id).first()
    session['game'] = game.id;
    session['gamename'] = game.name;
    session['gameshort'] = game.short;
    session['gameid'] = game.id;
    if not mod or not game:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(desc(Game.id)).first()
        session['game'] = ga.id;
        session['gamename'] = ga.name;
        session['gameshort'] = ga.short;
        session['gameid'] = ga.id;
        abort(404)
    else:
        session['game'] = game.id;
        session['gamename'] = game.name;
        session['gameshort'] = game.short;
        session['gameid'] = game.id;
    if any(m.id == mod.id for m in current_user.following):
        abort(418)
    event = FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .order_by(desc(FollowEvent.created))\
            .first()
    # Events are aggregated hourly
    if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1:
        event = FollowEvent()
        event.mod = mod
        event.delta = 1
        event.events = 1
        db.add(event)
        db.flush()
        db.commit()
        mod.follow_events.append(event)
    else:
        event.delta += 1
        event.events += 1
    mod.follower_count += 1
    current_user.following.append(mod)
    return { "success": True }
Esempio n. 35
0
def _connect_with_oauth_finalize(remote_user, provider):
    if not current_user:
        return 'Trying to associate an account, but not logged in?'

    auth = UserAuth.query.filter(UserAuth.provider == provider, UserAuth.remote_user == remote_user).first()
    if auth:
        if auth.user_id == current_user.id:
            # You're already set up.
            return redirect('/profile/%s/edit' % current_user.username)

        # This account is already connected with some user.
        full_name = list_defined_oauths()[provider]['full_name']
        return 'Your %s account is already connected to a SpaceDock account.' % full_name

    auth = UserAuth(current_user.id, remote_user, provider)
    db.add(auth)
    db.flush()  # So that /profile will display currectly

    return redirect('/profile/%s/edit' % current_user.username)
Esempio n. 36
0
def _connect_with_oauth_finalize(remote_user, provider):
    if not current_user:
        return 'Trying to associate an account, but not logged in?'

    auth = UserAuth.query.filter(UserAuth.provider == provider,
                                 UserAuth.remote_user == remote_user).first()
    if auth:
        if auth.user_id == current_user.id:
            # You're already set up.
            return redirect('/profile/%s/edit' % current_user.username)

        # This account is already connected with some user.
        full_name = list_defined_oauths()[provider]['full_name']
        return 'Your %s account is already connected to a KerbalStuff account.' % full_name

    auth = UserAuth(current_user.id, remote_user, provider)
    db.add(auth)
    db.flush()  # So that /profile will display currectly

    return redirect('/profile/%s/edit' % current_user.username)
Esempio n. 37
0
def get_or_create(mod: 'Mod') -> Optional[str]:
    protocol = _cfg('protocol')
    cdn_domain = _cfg('cdn-domain')

    if not mod.thumbnail:
        storage = _cfg('storage')
        if not mod.background:
            return None
        if not storage:
            return mod.background_url(protocol, cdn_domain)

        thumb_path = thumb_path_from_background_path(mod.background)

        thumb_disk_path = os.path.join(storage, thumb_path)
        background_disk_path = os.path.join(storage, mod.background)

        logging.debug("Checking file system for thumbnail")
        if not os.path.isfile(thumb_disk_path):
            if not os.path.isfile(background_disk_path):
                site_logger.warning(
                    'Background image does not exist, clearing path from db')
                mod.background = None
                db.add(mod)
                db.commit()
                return None
            try:
                logging.debug("Creating thumbnail")
                create(background_disk_path, thumb_disk_path)
            except Exception as e:
                site_logger.exception(e)
                return mod.background_url(protocol, cdn_domain)
        mod.thumbnail = thumb_path
        db.add(mod)
        db.commit()

    # Directly return the CDN path if we have any, so we don't have a redirect that breaks caching.
    if protocol and cdn_domain:
        return f'{protocol}://{cdn_domain}/{mod.thumbnail}'
    else:
        return url_for('mods.mod_thumbnail', mod_id=mod.id, mod_name=mod.name)
Esempio n. 38
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not current_user or current_user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = (
        DownloadEvent.query.filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)
        .order_by(desc(DownloadEvent.created))
        .first()
    )
    if not os.path.isfile(os.path.join(_cfg("storage"), version.download_path)):
        abort(404)

    if not "Range" in request.headers:
        # Events are aggregated hourly
        if not download or ((datetime.now() - download.created).seconds / 60 / 60) >= 1:
            download = DownloadEvent()
            download.mod = mod
            download.version = version
            download.downloads = 1
            db.add(download)
            db.flush()
            db.commit()
            mod.downloads.append(download)
        else:
            download.downloads += 1
        mod.download_count += 1

    response = make_response(send_file(os.path.join(_cfg("storage"), version.download_path), as_attachment=True))
    if _cfg("use-x-accel") == "true":
        response = make_response("")
        response.headers["Content-Type"] = "application/zip"
        response.headers["Content-Disposition"] = "attachment; filename=" + os.path.basename(version.download_path)
        response.headers["X-Accel-Redirect"] = "/internal/" + version.download_path
    return response
Esempio n. 39
0
def test_api_mod(client: 'FlaskClient[Response]') -> None:
    # Arrange
    game = Game(
        name='Kerbal Space Program',
        publisher=Publisher(name='SQUAD', ),
        short='kerbal-space-program',
        active=True,
    )
    mod = Mod(
        name='Test Mod',
        short_description='A mod for testing',
        description='A mod that we will use to test the API',
        user=User(
            username='******',
            description='Test author of a test mod',
            email='*****@*****.**',
            forumUsername='******',
            public=True,
        ),
        license='MIT',
        game=game,
        ckan=False,
        default_version=ModVersion(
            friendly_version="1.0.0.0",
            gameversion=GameVersion(
                friendly_version='1.2.3',
                game=game,
            ),
            download_path='/tmp/blah.zip',
            created=datetime.now(),
        ),
        published=True,
    )
    mod.default_version.mod = mod
    db.add(game)
    db.add(mod)
    db.commit()

    # Act
    publishers_resp = client.get('/api/publishers')
    games_resp = client.get('/api/games')
    kspversions_resp = client.get('/api/kspversions')
    gameversions_resp = client.get('/api/1/versions')
    mod_resp = client.get('/api/mod/1')
    mod_version_resp = client.get('/api/mod/1/latest')
    user_resp = client.get('/api/user/TestModAuthor')
    typeahead_resp = client.get('/api/typeahead/mod?game_id=1&query=Test')
    search_mod_resp = client.get('/api/search/mod?query=Test&page=1')
    search_user_resp = client.get('/api/search/user?query=Test&page=0')

    # Assert
    assert mod_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_mod(mod_resp.json)
    # Not returned by all APIs
    assert mod_resp.json[
        'description'] == 'A mod that we will use to test the API', 'Short description should match'

    assert kspversions_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_game_version(kspversions_resp.json[0])

    assert gameversions_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_game_version(gameversions_resp.json[0])

    assert games_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_game(games_resp.json[0])

    assert publishers_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_publisher(publishers_resp.json[0])

    assert mod_version_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_mod_version(mod_version_resp.json)

    assert user_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_user(user_resp.json)

    assert typeahead_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_mod(typeahead_resp.json[0])

    assert search_mod_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_mod(search_mod_resp.json[0])

    assert search_user_resp.status_code == status.HTTP_200_OK, 'Request should succeed'
    check_user(search_user_resp.json[0])
Esempio n. 40
0
def create_mod():
    if request.method == 'GET':
        return render_template("create.html")
    else:
        user = get_user()
        if not user.public:
            # Only public users can create mods
            # /create tells users about this
            return redirect("/create/mod")
        name = request.form.get('name')
        description = request.form.get('description')
        short_description = request.form.get('short-description')
        version = request.form.get('version')
        ksp_version = request.form.get('ksp-version')
        external_link = request.form.get('external-link')
        license = request.form.get('license')
        source_link = request.form.get('source-code')
        donation_link = request.form.get('donation')
        screenshots = request.form.get('screenshots')
        videos = request.form.get('videos')
        background = request.form.get('backgroundMedia')
        zipball = request.files.get('zipball')
        # Validate
        if not name \
            or not short_description \
            or not description \
            or not version \
            or not ksp_version \
            or not license \
            or not zipball:
            # Client side validation means that they're just being pricks if they
            # get here, so we don't need to show them a pretty error message
            abort(400)
        screenshot_list = screenshots.split(',')
        video_list = videos.split(',')
        # Validation, continued
        if len(name) > 100 \
            or len(description) > 100000 \
            or len(donation_link) > 512 \
            or len(external_link) > 512 \
            or len(license) > 128 \
            or len(source_link) > 256 \
            or len(background) > 32 \
            or len(screenshot_list) > 5 \
            or len(video_list) > 2:
            abort(400)
        mod = Mod()
        mod.user = user
        mod.name = name
        mod.description = description
        mod.short_description = short_description
        mod.external_link = external_link
        mod.license = license
        mod.source_link = source_link
        mod.donation_link = donation_link
        mod.background = background
        # Do media
        for screenshot in screenshot_list:
            if screenshot:
                r = requests.get('https://mediacru.sh/' + screenshot + '.json')
                if r.status_code != 200:
                    abort(400)
                j = r.json()
                data = ''
                if j['blob_type'] == 'image':
                    for f in j['files']:
                        if f['type'] == 'image/jpeg' or f['type'] == 'image/png':
                            data = f['file']
                else:
                    abort(400)
                m = Media(j['hash'], j['blob_type'], data)
                mod.medias.append(m)
        for video in video_list:
            if video:
                r = requests.get('https://mediacru.sh/' + video + '.json')
                if r.status_code != 200:
                    abort(400)
                j = r.json()
                data = ''
                if j['blob_type'] == 'video':
                    data = j['hash']
                else:
                    abort(400)
                m = Media(j['hash'], j['blob_type'], data)
                mod.medias.append(m)
                db.add(m)
        # Save zipball
        filename = secure_filename(name) + '-' + secure_filename(version) + '.zip'
        base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(name))
        full_path = os.path.join(_cfg('storage'), base_path)
        if not os.path.exists(full_path):
            os.makedirs(full_path)
        path = os.path.join(full_path, filename)
        if os.path.isfile(path):
            # We already have this version
            # TODO: Error message
            abort(400)
        zipball.save(path)
        if not zipfile.is_zipfile(path):
            os.remove(path)
            abort(400) # TODO: Error message
        version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename))
        mod.versions.append(version)
        db.add(version)
        # Save database entry
        db.add(mod)
        db.commit()
        return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
Esempio n. 41
0
def mod(id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == id).first()
    if not mod:
        abort(404)
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not mod.published and not editable:
        abort(401)
    videos = list()
    screens = list()
    latest = mod.versions[0]
    screenshot_list = ",".join([s.data for s in mod.media if s.type == 'image'])
    video_list = ",".join([s.data for s in mod.media if s.type == 'video'])
    for m in mod.medias:
        if m.type == 'video':
            videos.append(m)
        else:
            screens.append(m)
    referral = request.referrer
    if referral:
        host = urllib.parse.urlparse(referral).hostname
        event = ReferralEvent.query\
                .filter(ReferralEvent.mod_id == mod.id)\
                .filter(ReferralEvent.host == host)\
                .first()
        if not event:
            event = ReferralEvent()
            event.mod = mod
            event.events = 1
            event.host = host
            mod.referrals.append(event)
            db.add(event)
        else:
            event.events += 1
        db.commit()
    download_stats = None
    follower_stats = None
    referrals = None
    json_versions = None
    thirty_days_ago = datetime.now() - timedelta(days=30)
    if editable:
        referrals = list()
        for r in ReferralEvent.query\
            .filter(ReferralEvent.mod_id == mod.id)\
            .order_by(desc(ReferralEvent.events)):
            referrals.append( { 'host': r.host, 'count': r.events } )
        download_stats = list()
        for d in DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id)\
            .filter(DownloadEvent.created > thirty_days_ago)\
            .order_by(DownloadEvent.created):
            download_stats.append(dumb_object(d))
        follower_stats = list()
        for f in FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .filter(FollowEvent.created > thirty_days_ago)\
            .order_by(FollowEvent.created):
            follower_stats.append(dumb_object(f))
        json_versions = list()
        for v in mod.versions:
            json_versions.append({ 'name': v.friendly_version, 'id': v.id })
    return render_template("mod.html",
        **{
            'mod': mod,
            'videos': videos,
            'screens': screens,
            'latest': latest,
            'safe_name': secure_filename(mod.name)[:64],
            'featured': any(Featured.query.filter(Featured.mod_id == mod.id).all()),
            'editable': editable,
            'screenshot_list': screenshot_list,
            'video_list': video_list,
            'download_stats': download_stats,
            'follower_stats': follower_stats,
            'referrals': referrals,
            'json_versions': json_versions,
            'thirty_days_ago': thirty_days_ago
        })
Esempio n. 42
0
def mod(id, mod_name):
    games = Game.query.filter(Game.active == True).order_by(desc(
        Game.id)).all()
    if session.get('gameid'):
        if session['gameid']:
            ga = Game.query.filter(Game.id == session['gameid']).order_by(
                desc(Game.id)).first()
        else:
            ga = Game.query.filter(
                Game.short == 'kerbal-space-program').order_by(desc(
                    Game.id)).first()
    else:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(
            desc(Game.id)).first()
    session['game'] = ga.id
    session['gamename'] = ga.name
    session['gameshort'] = ga.short
    session['gameid'] = ga.id
    mod = Mod.query.filter(Mod.id == id, Mod.game_id == ga.id).first()
    if not mod:
        abort(404)
    if not mod or not ga:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
    if not mod.published and not editable:
        abort(401)
    latest = mod.default_version()
    referral = request.referrer
    if referral:
        host = urllib.parse.urlparse(referral).hostname
        event = ReferralEvent.query\
                .filter(ReferralEvent.mod_id == mod.id)\
                .filter(ReferralEvent.host == host)\
                .first()
        if not event:
            event = ReferralEvent()
            event.mod = mod
            event.events = 1
            event.host = host
            db.add(event)
            db.flush()
            db.commit()
            mod.referrals.append(event)
        else:
            event.events += 1
    download_stats = None
    follower_stats = None
    referrals = None
    json_versions = None
    thirty_days_ago = datetime.now() - timedelta(days=30)
    referrals = list()
    for r in ReferralEvent.query\
        .filter(ReferralEvent.mod_id == mod.id)\
        .order_by(desc(ReferralEvent.events)):
        referrals.append({'host': r.host, 'count': r.events})
    download_stats = list()
    for d in DownloadEvent.query\
        .filter(DownloadEvent.mod_id == mod.id)\
        .filter(DownloadEvent.created > thirty_days_ago)\
        .order_by(DownloadEvent.created):
        download_stats.append(dumb_object(d))
    follower_stats = list()
    for f in FollowEvent.query\
        .filter(FollowEvent.mod_id == mod.id)\
        .filter(FollowEvent.created > thirty_days_ago)\
        .order_by(FollowEvent.created):
        follower_stats.append(dumb_object(f))
    json_versions = list()
    for v in mod.versions:
        json_versions.append({'name': v.friendly_version, 'id': v.id})
    if request.args.get('noedit') != None:
        editable = False
    forumThread = False
    if mod.external_link != None:
        try:
            u = urlparse(mod.external_link)
            if u.netloc == 'forum.kerbalspaceprogram.com':
                forumThread = True
        except e:
            print(e)
            pass
    total_authors = 1
    pending_invite = False
    owner = editable
    for a in mod.shared_authors:
        if a.accepted:
            total_authors += 1
        if current_user:
            if current_user.id == a.user_id and not a.accepted:
                pending_invite = True
            if current_user.id == a.user_id and a.accepted:
                editable = True
    games = Game.query.filter(Game.active == True).order_by(desc(
        Game.id)).all()

    game_versions = GameVersion.query.filter(
        GameVersion.game_id == mod.game_id).order_by(desc(
            GameVersion.id)).all()

    outdated = False
    if latest:
        outdated = latest.gameversion.id != game_versions[
            0].id and latest.gameversion.friendly_version != '1.0.5'
    return render_template(
        "mod.html", **{
            'mod':
            mod,
            'latest':
            latest,
            'safe_name':
            secure_filename(mod.name)[:64],
            'featured':
            any(Featured.query.filter(Featured.mod_id == mod.id).all()),
            'editable':
            editable,
            'owner':
            owner,
            'pending_invite':
            pending_invite,
            'download_stats':
            download_stats,
            'follower_stats':
            follower_stats,
            'referrals':
            referrals,
            'json_versions':
            json_versions,
            'thirty_days_ago':
            thirty_days_ago,
            'share_link':
            urllib.parse.quote_plus(
                _cfg("protocol") + "://" + _cfg("domain") + "/mod/" +
                str(mod.id)),
            'game_versions':
            game_versions,
            'games':
            games,
            'outdated':
            outdated,
            'forum_thread':
            forumThread,
            'new':
            request.args.get('new') != None,
            'stupid_user':
            request.args.get('stupid_user') != None,
            'total_authors':
            total_authors,
            "site_name":
            _cfg('site-name'),
            "support_mail":
            _cfg('support-mail'),
            'ga':
            ga
        })
Esempio n. 43
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    game = Game.query.filter(Game.id == mod.game_id).first()
    session['game'] = game.id
    session['gamename'] = game.name
    session['gameshort'] = game.short
    session['gameid'] = game.id
    if not mod or not game:
        ga = Game.query.filter(Game.short == 'kerbal-space-program').order_by(
            desc(Game.id)).first()
        session['game'] = ga.id
        session['gamename'] = ga.name
        session['gameshort'] = ga.short
        session['gameid'] = ga.id
        abort(404)
    else:
        session['game'] = game.id
        session['gamename'] = game.name
        session['gameshort'] = game.short
        session['gameid'] = game.id
    if not mod.published and (not current_user
                              or current_user.id != mod.user_id):
        abort(401)
    version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \
            ModVersion.friendly_version == version).first()
    if not version:
        abort(404)
    download = DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\
            .order_by(desc(DownloadEvent.created))\
            .first()
    if not os.path.isfile(os.path.join(_cfg('storage'),
                                       version.download_path)):
        abort(404)

    if not 'Range' in request.headers:
        # Events are aggregated hourly
        if not download or (
            (datetime.now() - download.created).seconds / 60 / 60) >= 1:
            download = DownloadEvent()
            download.mod = mod
            download.version = version
            download.downloads = 1
            db.add(download)
            db.flush()
            db.commit()
            mod.downloads.append(download)
        else:
            download.downloads += 1
        mod.download_count += 1

    if _cfg("cdn-domain"):
        return redirect("http://" + _cfg("cdn-domain") + '/' +
                        version.download_path,
                        code=302)

    response = None
    if _cfg("use-x-accel") == 'nginx':
        response = make_response("")
        response.headers['Content-Type'] = 'application/zip'
        response.headers[
            'Content-Disposition'] = 'attachment; filename=' + os.path.basename(
                version.download_path)
        response.headers[
            'X-Accel-Redirect'] = '/internal/' + version.download_path
    if _cfg("use-x-accel") == 'apache':
        response = make_response("")
        response.headers['Content-Type'] = 'application/zip'
        response.headers[
            'Content-Disposition'] = 'attachment; filename=' + os.path.basename(
                version.download_path)
        response.headers['X-Sendfile'] = os.path.join(_cfg('storage'),
                                                      version.download_path)
    if response is None:
        response = make_response(
            send_file(os.path.join(_cfg('storage'), version.download_path),
                      as_attachment=True))
    return response
Esempio n. 44
0
def mod(id, mod_name):
    mod = Mod.query.filter(Mod.id == id).first()
    if not mod:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
    if not mod.published and not editable:
        abort(401)
    latest = mod.default_version()
    referral = request.referrer
    if referral:
        host = urllib.parse.urlparse(referral).hostname
        event = ReferralEvent.query.filter(ReferralEvent.mod_id == mod.id).filter(ReferralEvent.host == host).first()
        if not event:
            event = ReferralEvent()
            event.mod = mod
            event.events = 1
            event.host = host
            db.add(event)
            db.flush()
            db.commit()
            mod.referrals.append(event)
        else:
            event.events += 1
    download_stats = None
    follower_stats = None
    referrals = None
    json_versions = None
    thirty_days_ago = datetime.now() - timedelta(days=30)
    referrals = list()
    for r in ReferralEvent.query.filter(ReferralEvent.mod_id == mod.id).order_by(desc(ReferralEvent.events)):
        referrals.append({"host": r.host, "count": r.events})
    download_stats = list()
    for d in (
        DownloadEvent.query.filter(DownloadEvent.mod_id == mod.id)
        .filter(DownloadEvent.created > thirty_days_ago)
        .order_by(DownloadEvent.created)
    ):
        download_stats.append(dumb_object(d))
    follower_stats = list()
    for f in (
        FollowEvent.query.filter(FollowEvent.mod_id == mod.id)
        .filter(FollowEvent.created > thirty_days_ago)
        .order_by(FollowEvent.created)
    ):
        follower_stats.append(dumb_object(f))
    json_versions = list()
    for v in mod.versions:
        json_versions.append({"name": v.friendly_version, "id": v.id})
    if request.args.get("noedit") != None:
        editable = False
    forumThread = False
    if mod.external_link != None:
        try:
            u = urlparse(mod.external_link)
            if u.netloc == "forum.kerbalspaceprogram.com":
                forumThread = True
        except e:
            print(e)
            pass
    total_authors = 1
    pending_invite = False
    owner = editable
    for a in mod.shared_authors:
        if a.accepted:
            total_authors += 1
        if current_user:
            if current_user.id == a.user_id and not a.accepted:
                pending_invite = True
            if current_user.id == a.user_id and a.accepted:
                editable = True
    game_versions = GameVersion.query.order_by(desc(GameVersion.id)).all()
    outdated = False
    if latest:
        outdated = game_versions[0].friendly_version != latest.ksp_version
    return render_template(
        "mod.html",
        **{
            "mod": mod,
            "latest": latest,
            "safe_name": secure_filename(mod.name)[:64],
            "featured": any(Featured.query.filter(Featured.mod_id == mod.id).all()),
            "editable": editable,
            "owner": owner,
            "pending_invite": pending_invite,
            "download_stats": download_stats,
            "follower_stats": follower_stats,
            "referrals": referrals,
            "json_versions": json_versions,
            "thirty_days_ago": thirty_days_ago,
            "share_link": urllib.parse.quote_plus(_cfg("protocol") + "://" + _cfg("domain") + "/mod/" + str(mod.id)),
            "game_versions": game_versions,
            "outdated": outdated,
            "forum_thread": forumThread,
            "new": request.args.get("new") != None,
            "stupid_user": request.args.get("stupid_user") != None,
            "total_authors": total_authors,
        }
    )
Esempio n. 45
0
def create_mod():
    if request.method == 'GET':
        return render_template("create.html")
    else:
        user = get_user()
        if not user.public:
            # Only public users can create mods
            # /create tells users about this
            return redirect("/create/mod")
        name = request.form.get('name')
        description = request.form.get('description')
        short_description = request.form.get('short-description')
        version = request.form.get('version')
        ksp_version = request.form.get('ksp-version')
        external_link = request.form.get('external-link')
        license = request.form.get('license')
        source_link = request.form.get('source-code')
        donation_link = request.form.get('donation')
        screenshots = request.form.get('screenshots')
        videos = request.form.get('videos')
        background = request.form.get('backgroundMedia')
        zipball = request.files.get('zipball')
        # Validate
        if not name \
            or not short_description \
            or not description \
            or not version \
            or not ksp_version \
            or not license \
            or not zipball:
            # Client side validation means that they're just being pricks if they
            # get here, so we don't need to show them a pretty error message
            abort(400)
        screenshot_list = screenshots.split(',')
        video_list = videos.split(',')
        # Validation, continued
        if len(name) > 100 \
            or len(description) > 100000 \
            or len(donation_link) > 512 \
            or len(external_link) > 512 \
            or len(license) > 128 \
            or len(source_link) > 256 \
            or len(background) > 32 \
            or len(screenshot_list) > 5 \
            or len(video_list) > 2:
            abort(400)
        mod = Mod()
        mod.user = user
        mod.name = name
        mod.description = description
        mod.short_description = short_description
        mod.external_link = external_link
        mod.license = license
        mod.source_link = source_link
        mod.donation_link = donation_link
        mod.background = background
        # Do media
        for screenshot in screenshot_list:
            if screenshot:
                r = requests.get('https://mediacru.sh/' + screenshot + '.json')
                if r.status_code != 200:
                    abort(400)
                j = r.json()
                data = ''
                if j['blob_type'] == 'image':
                    for f in j['files']:
                        if f['type'] == 'image/jpeg' or f[
                                'type'] == 'image/png':
                            data = f['file']
                else:
                    abort(400)
                m = Media(j['hash'], j['blob_type'], data)
                mod.medias.append(m)
        for video in video_list:
            if video:
                r = requests.get('https://mediacru.sh/' + video + '.json')
                if r.status_code != 200:
                    abort(400)
                j = r.json()
                data = ''
                if j['blob_type'] == 'video':
                    data = j['hash']
                else:
                    abort(400)
                m = Media(j['hash'], j['blob_type'], data)
                mod.medias.append(m)
                db.add(m)
        # Save zipball
        filename = secure_filename(name) + '-' + secure_filename(
            version) + '.zip'
        base_path = os.path.join(
            secure_filename(user.username) + '_' + str(user.id),
            secure_filename(name))
        full_path = os.path.join(_cfg('storage'), base_path)
        if not os.path.exists(full_path):
            os.makedirs(full_path)
        path = os.path.join(full_path, filename)
        if os.path.isfile(path):
            # We already have this version
            # TODO: Error message
            abort(400)
        zipball.save(path)
        if not zipfile.is_zipfile(path):
            os.remove(path)
            abort(400)  # TODO: Error message
        version = ModVersion(secure_filename(version), ksp_version,
                             os.path.join(base_path, filename))
        mod.versions.append(version)
        db.add(version)
        # Save database entry
        db.add(mod)
        db.commit()
        return redirect('/mod/' + str(mod.id) + '/' +
                        secure_filename(mod.name)[:64])
Esempio n. 46
0
def mod(id, mod_name):
    mod = Mod.query.filter(Mod.id == id).first()
    if not mod:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
    if not mod.published and not editable:
        abort(401)
    latest = mod.default_version()
    referral = request.referrer
    if referral:
        host = urllib.parse.urlparse(referral).hostname
        event = ReferralEvent.query\
                .filter(ReferralEvent.mod_id == mod.id)\
                .filter(ReferralEvent.host == host)\
                .first()
        if not event:
            event = ReferralEvent()
            event.mod = mod
            event.events = 1
            event.host = host
            db.add(event)
            db.flush()
            db.commit()
            mod.referrals.append(event)
        else:
            event.events += 1
    download_stats = None
    follower_stats = None
    referrals = None
    json_versions = None
    thirty_days_ago = datetime.now() - timedelta(days=30)
    referrals = list()
    for r in ReferralEvent.query\
        .filter(ReferralEvent.mod_id == mod.id)\
        .order_by(desc(ReferralEvent.events)):
        referrals.append( { 'host': r.host, 'count': r.events } )
    download_stats = list()
    for d in DownloadEvent.query\
        .filter(DownloadEvent.mod_id == mod.id)\
        .filter(DownloadEvent.created > thirty_days_ago)\
        .order_by(DownloadEvent.created):
        download_stats.append(dumb_object(d))
    follower_stats = list()
    for f in FollowEvent.query\
        .filter(FollowEvent.mod_id == mod.id)\
        .filter(FollowEvent.created > thirty_days_ago)\
        .order_by(FollowEvent.created):
        follower_stats.append(dumb_object(f))
    json_versions = list()
    for v in mod.versions:
        json_versions.append({ 'name': v.friendly_version, 'id': v.id })
    if request.args.get('noedit') != None:
        editable = False
    forumThread = False
    if mod.external_link != None:
        try:
            u = urlparse(mod.external_link)
            if u.netloc == 'forum.kerbalspaceprogram.com':
                forumThread = True
        except e:
            print(e)
            pass
    total_authors = 1
    pending_invite = False
    owner = editable
    for a in mod.shared_authors:
        if a.accepted:
            total_authors += 1
        if current_user:
            if current_user.id == a.user_id and not a.accepted:
                pending_invite = True
            if current_user.id == a.user_id and a.accepted:
                editable = True
    game_versions = GameVersion.query.order_by(desc(GameVersion.id)).all()
    outdated = False
    if latest:
        outdated = game_versions[0].friendly_version != latest.ksp_version
    return render_template("mod.html",
        **{
            'mod': mod,
            'latest': latest,
            'safe_name': secure_filename(mod.name)[:64],
            'featured': any(Featured.query.filter(Featured.mod_id == mod.id).all()),
            'editable': editable,
            'owner': owner,
            'pending_invite': pending_invite,
            'download_stats': download_stats,
            'follower_stats': follower_stats,
            'referrals': referrals,
            'json_versions': json_versions,
            'thirty_days_ago': thirty_days_ago,
            'share_link': urllib.parse.quote_plus(_cfg("protocol") + "://" + _cfg("domain") + "/mod/" + str(mod.id)),
            'game_versions': game_versions,
            'outdated': outdated,
            'forum_thread': forumThread,
            'new': request.args.get('new') != None,
            'stupid_user': request.args.get('stupid_user') != None,
            'total_authors': total_authors,
			"site_name": _cfg('site-name'), 
			"support_mail": _cfg('support-mail')
        })
Esempio n. 47
0
from alembic import command
from KerbalStuff.objects import *
from KerbalStuff.database import db

# Make sure tables are created
alembic_cfg = Config("alembic.ini")
command.stamp(alembic_cfg, "head")
command.upgrade(alembic_cfg, "head")

# Create admin user if doesn't exist
if not User.query.filter(User.username.ilike("admin")).first():
    admin = User("admin", "*****@*****.**", "development")
    admin.admin = True
    user.public = True
    admin.confirmation = None
    db.add(admin)
    db.commit()

# Create normal user if doesn't exist
if not User.query.filter(User.username.ilike("user")).first():
    user = User("user", "*****@*****.**", "development")
    user.public = True
    user.confirmation = None
    db.add(user)
    db.commit()

if not Publisher.query.first():
    pub = Publisher("Squad")
    db.add(pub)
    db.commit()
Esempio n. 48
0
def mod(id, mod_name):
    user = get_user()
    mod = Mod.query.filter(Mod.id == id).first()
    if not mod:
        abort(404)
    editable = False
    if user:
        if user.admin:
            editable = True
        if user.id == mod.user_id:
            editable = True
    if not mod.published and not editable:
        abort(401)
    videos = list()
    screens = list()
    latest = mod.versions[0]
    screenshot_list = ",".join(
        [s.data for s in mod.media if s.type == 'image'])
    video_list = ",".join([s.data for s in mod.media if s.type == 'video'])
    for m in mod.medias:
        if m.type == 'video':
            videos.append(m)
        else:
            screens.append(m)
    referral = request.referrer
    if referral:
        host = urllib.parse.urlparse(referral).hostname
        event = ReferralEvent.query\
                .filter(ReferralEvent.mod_id == mod.id)\
                .filter(ReferralEvent.host == host)\
                .first()
        if not event:
            event = ReferralEvent()
            event.mod = mod
            event.events = 1
            event.host = host
            mod.referrals.append(event)
            db.add(event)
        else:
            event.events += 1
        db.commit()
    download_stats = None
    follower_stats = None
    referrals = None
    json_versions = None
    thirty_days_ago = datetime.now() - timedelta(days=30)
    if editable:
        referrals = list()
        for r in ReferralEvent.query\
            .filter(ReferralEvent.mod_id == mod.id)\
            .order_by(desc(ReferralEvent.events)):
            referrals.append({'host': r.host, 'count': r.events})
        download_stats = list()
        for d in DownloadEvent.query\
            .filter(DownloadEvent.mod_id == mod.id)\
            .filter(DownloadEvent.created > thirty_days_ago)\
            .order_by(DownloadEvent.created):
            download_stats.append(dumb_object(d))
        follower_stats = list()
        for f in FollowEvent.query\
            .filter(FollowEvent.mod_id == mod.id)\
            .filter(FollowEvent.created > thirty_days_ago)\
            .order_by(FollowEvent.created):
            follower_stats.append(dumb_object(f))
        json_versions = list()
        for v in mod.versions:
            json_versions.append({'name': v.friendly_version, 'id': v.id})
    return render_template(
        "mod.html", **{
            'mod': mod,
            'videos': videos,
            'screens': screens,
            'latest': latest,
            'safe_name': secure_filename(mod.name)[:64],
            'featured':
            any(Featured.query.filter(Featured.mod_id == mod.id).all()),
            'editable': editable,
            'screenshot_list': screenshot_list,
            'video_list': video_list,
            'download_stats': download_stats,
            'follower_stats': follower_stats,
            'referrals': referrals,
            'json_versions': json_versions,
            'thirty_days_ago': thirty_days_ago
        })
Esempio n. 49
0
from alembic.config import Config
from alembic import command
from KerbalStuff.objects import *
from KerbalStuff.database import db

# Make sure tables are created
alembic_cfg = Config("alembic.ini")
command.stamp(alembic_cfg, "head")
command.upgrade(alembic_cfg, "head")

# Create admin user if doesn't exist
if not User.query.filter(User.username.ilike("admin")).first():
    admin = User("admin", "*****@*****.**", "development")
    admin.admin = True
    admin.confirmation = None
    db.add(admin)
    db.commit()

# Create normal user if doesn't exist
if not User.query.filter(User.username.ilike("user")).first():
    user = User("user", "*****@*****.**", "development")
    user.confirmation = None
    db.add(user)
    db.commit()