Пример #1
0
def handleMove(environ, start_response):
    user = environ['user']
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']
    versionId = missionJson['versionId']
    # If you're a MM user and this is your mission, or you're a low admin
    if not (utils.checkUserPermissions(
            user, 1, missionId=missionId, collector=utils.AND)
            or utils.checkUserPermissions(user, 2)):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c = utils.getCursor()
    c.execute("select name from versions where id = ?", [versionId])

    fileName = c.fetchone()[0]
    if Path(utils.missionMakerDir + "/" + fileName).is_file():
        copyfile(utils.missionMakerDir + "/" + fileName,
                 utils.missionMainDir + "/" + fileName)
        c.execute("update versions set existsOnMain=1 where id = ?",
                  [versionId])
        c.connection.commit()
        c.connection.close()

    start_response("200 OK", [])
    return []
Пример #2
0
def handleSaveMission(environ, start_response):
    c = utils.getCursor()
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    # create a blank row, then update that row so that we don't have 2 different statements
    if 'missionId' not in missionJson:
        c.execute("insert into missions (missionName) values (?)",
                  [missionJson['missionName']])
        c.execute("select max(id) from missions")
        missionId = c.fetchone()[0]
        hasPermissions = utils.checkUserPermissions(environ['user'], 0)
    else:
        missionId = missionJson['missionId']
        c.execute("select * from missions where id = ?", [missionId])
        mission = c.fetchone()
        if mission is None:
            start_response("500 Internal Server Response", [])
            return [
                "Stop trying to edit a mission that doesn't exist".encode()
            ]
        hasPermissions = utils.checkUserPermissions(environ['user'], 2,
                                                    missionId)

    if not hasPermissions:
        start_response("403 Permission Denied", [])
        return ["Access Denied"]
    query, params = constructQuery(missionJson)
    params.append(missionId)

    c.execute("update missions set " + query + "where id=?", params)
    c.connection.commit()
    c.connection.close()
    start_response("201 Created", [])
    return [(str(missionId)).encode()]
Пример #3
0
def handleComment(environ, start_response):
    user = environ['user']
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']
    comment = html.escape(missionJson['comment'])
    rejection = True if 'rejection' in missionJson and missionJson['rejection'] == True else False
    # If you're a MM user and this is your mission, or you're a low admin
    if rejection and not (
                utils.checkUserPermissions(user, 1, missionId=missionId,
                                           collector=utils.AND) or utils.checkUserPermissions(
            user, 2)):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c = utils.getCursor()
    c.execute("select name, id from versions where id = (select max(id) from versions where missionId = ?)",
              [missionId])

    versionRow = c.fetchone()
    fileName = versionRow[0]
    versionId = versionRow[1]

    if rejection:
        c.execute("UPDATE missions SET status ='Broken' WHERE id = ?", [missionId])
        c.execute("UPDATE versions SET requestedTransfer=0, requestedTesting=0 WHERE id = ?", [versionId])
    c.execute("insert into comments (missionId, user, contents, createDate, versionId) values (?,?,?,?, ?)",
              [missionId, user.login, comment, datetime.now(), versionId])

    if utils.discordHookUrl != '':
        c.execute("select missionName, missionAuthor from missions where id = ?", [missionId])
        missionFromDb = c.fetchone()
        missionName = missionFromDb[0]
        unawareAuthors = filter(lambda author: author.strip() != user.login, [author for author in missionFromDb[1].split(",")])
        missionAuthorDiscordIds = filter(None, [authorToUser(author) for author in unawareAuthors])

        # Only send the message if there is at least one ID to send to
        if len(list(missionAuthorDiscordIds)) > 0:
            missionAuthorDiscordIds = ['<@' + discordId + ">" for discordId in missionAuthorDiscordIds]

            if rejection:
                payload = {
                    'content': 'Despair  ' + ' '.join(missionAuthorDiscordIds) + '! ' + fileName + ' has been rejected'}
            else:
                payload = {'content': ' '.join(missionAuthorDiscordIds) + '! ' + missionName + ' has a new comment. '}
            r = requests.post(utils.discordHookUrl, data=payload)

    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #4
0
def handleMove(environ, start_response):
    user = environ['user']
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']
    versionId = missionJson['versionId']
    # If you're a MM user and this is your mission, or you're a low admin
    if not (utils.checkUserPermissions(
            user, 1, missionId=missionId, collector=utils.AND)
            or utils.checkUserPermissions(user, 2)):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c = utils.getCursor()
    c.execute("select name from versions where id = ?", [versionId])

    fileName = c.fetchone()[0]
    if Path(utils.missionMakerDir + "/" + fileName).exists():
        copyfile(utils.missionMakerDir + "/" + fileName,
                 utils.missionMainDir + "/" + fileName)
        c.execute(
            "UPDATE versions SET existsOnMain=1, requestedTransfer=0, requestedTesting=0 WHERE id = ?",
            [versionId])

        c.execute("update missions set status ='Ready' where id = ?",
                  [missionId])

    if utils.discordHookUrl != '':
        c.execute("select missionAuthor from missions where id = ?",
                  [missionId])
        missionFromDb = c.fetchone()
        missionAuthorDiscordIds = filter(
            None,
            [authorToUser(author) for author in missionFromDb[0].split(",")])
        missionAuthorDiscordIds = [
            '<@' + discordId + ">" for discordId in missionAuthorDiscordIds
        ]

        payload = {
            'content':
            'Rejoice  ' + ' '.join(missionAuthorDiscordIds) + '! ' + fileName +
            ' has been accepted'
        }

        r = requests.post(utils.discordHookUrl, data=payload)

    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #5
0
def handleTesting(environ, start_response):
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']
    versionId = missionJson['versionId']
    # If you're a MM user and this is your mission, or you're a low admin
    if not utils.checkUserPermissions(environ['user'], 1, missionId):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c = utils.getCursor()
    c.execute("SELECT name FROM versions WHERE id = ?", [versionId])

    version = c.fetchone()
    fileName = version[0]
    if Path(utils.missionMakerDir + "/" + fileName).is_file():
        c.execute("UPDATE missions SET status='Testing' WHERE id = ?", [missionId])
        c.execute("UPDATE versions SET requestedTesting=1 WHERE id = ?", [versionId])

    if utils.discordHookUrl != '':
        c.execute("SELECT missionName, missionAuthor FROM missions WHERE id = ?", [missionId])
        missionStuff = c.fetchone()
        missionName = missionStuff[0]
        missionAuthor = missionStuff[1]

        payload = {'content': 'Rejoice Comrades! ' + missionAuthor
                              + ' has prepared a new adventure for us!\n' +
                              missionName + ' now has ' + fileName + ' requested for testing.'}
        r = requests.post(utils.discordHookUrl, data=payload)

    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #6
0
def handlePermissionLevel(environ, start_response):
    c = utils.getCursor()
    permissionLevelString = utils.environToContents(environ)
    permissionLevelJson = json.loads(permissionLevelString)
    userId = permissionLevelJson['id']
    permissionLevel = permissionLevelJson['permissionLevel']
    if utils.checkUserPermissions(environ['user'], 3):
        c.execute("update users set permissionLevel = ? where id = ?",
                  [permissionLevel, userId])

        c.execute("select * from users where permissionLevel = 3")
        if c.fetchone() is None:
            start_response("500 Internal Server Error", [])
            return [
                "No admin users found, there must be at least one high admin (3)"
                .encode()
            ]
        else:
            start_response("200 OK", [])
            c.connection.commit()
            c.connection.close()
    else:
        start_response("403 Permission Denied", [])
        return ["Access Denied".encode()]
    return []
Пример #7
0
def handleCleanup(environ, start_response):
    c = utils.getCursor()
    # if you're a low admin
    if not utils.checkUserPermissions(environ['user'], 2):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    for origin in ['main', 'missionMaker']:
        if origin == 'main':
            missionDirPrefix = utils.missionMainDir
            missionArchivePrefix = utils.missionMainArchive
            toBeArchivedProperty = 'toBeArchivedMain'
            toBeDeletedProperty = 'toBeDeletedMain'
            existsProperty = 'existsOnMain'
        else:
            missionDirPrefix = utils.missionMakerDir
            missionArchivePrefix = utils.missionMakerArchive
            toBeArchivedProperty = 'toBeArchivedMM'
            toBeDeletedProperty = 'toBeDeletedMM'
            existsProperty = 'existsOnMM'

        c.execute('''select * from versions where ''' + toBeArchivedProperty +
                  ''' = 1''')
        toBeArchived = c.fetchall()

        for forArchival in toBeArchived:
            with open(missionDirPrefix + "/" + forArchival['name'],
                      'rb') as f_in:
                with gzip.open(
                        os.path.join(missionArchivePrefix,
                                     forArchival['name'] + ".gz"),
                        'wb') as f_out:
                    shutil.copyfileobj(f_in, f_out)
                    os.remove(f_in.name)

        c.execute('''select * from versions where ''' + toBeDeletedProperty +
                  ''' = 1''')
        toBeDeleted = c.fetchall()
        for deleteMe in toBeDeleted:
            os.remove(os.path.join(missionDirPrefix, deleteMe['name']))

        c.execute("update versions set " + existsProperty + " = 0, " +
                  toBeArchivedProperty + " = 0, " + toBeDeletedProperty +
                  " = 0 where " + toBeArchivedProperty + " = 1 or " +
                  toBeDeletedProperty + " = 1")
    c.connection.commit()
    c.connection.close()

    start_response("200 OK", [])
    return []
Пример #8
0
def handleSessionDelete(environ, start_response):
    c = utils.getCursor()

    sessionJsonString = utils.environToContents(environ)
    sessionJson = json.loads(sessionJsonString)
    sessionId = sessionJson['sessionId']

    if not utils.checkUserPermissions(environ['user'], 2):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c.execute("delete from sessions where id = ?", [sessionId])
    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #9
0
def handleEditSession(environ, start_response):
    c = utils.getCursor()
    editSessionString = utils.environToContents(environ)
    editSessionJson = json.loads(editSessionString)
    sessionDate = editSessionJson['date']

    # if you're a low admin
    if not utils.checkUserPermissions(environ['user'], 2):
        start_response("403 Permission Denied", [])
        return ["Access Denied".encode()]

    if 'id' not in editSessionJson:
        c.execute("insert into sessions (date) values (?)", [sessionDate])
        c.execute("select max(id) from sessions")
        sessionId = c.fetchone()[0]
    else:
        sessionId = editSessionJson['id']

    c.execute("select missionNames from sessions where id = ?", [sessionId])
    existingMissionNames = c.fetchone()

    c.execute(
        "update sessions set missionNames = ?, host = ?, name = ?, players = ?, date = ? where id = ? ",
        toParams(editSessionJson, sessionId))
    missions = editSessionJson['missionNames']

    newMissions = []

    if existingMissionNames['missionNames'] is not None:
        existingMissionNames = existingMissionNames['missionNames'].split(",")
        for mission in missions:
            if mission in existingMissionNames:
                existingMissionNames.remove(mission)
            else:
                newMissions.append(mission)
    else:
        newMissions = missions

    for mission in newMissions:
        c.execute(
            "update missions set playedCounter = playedCounter+1, lastPlayed=? where missionName =?",
            [sessionDate, mission])
    c.connection.commit()
    c.connection.close()
    start_response("201 Created", [])
    return [("location:" + str(sessionId)).encode()]
Пример #10
0
def handleMissionDelete(environ, start_response):
    c = utils.getCursor()

    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']

    # if you're a low admin or this is your mission
    if not utils.checkUserPermissions(environ['user'], 2, missionId):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    c.execute("delete from versions where missionId = ?", [missionId])
    c.execute("delete from missions where id = ?", [missionId])
    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #11
0
def handleCleanup(environ, start_response):
    c = utils.getCursor()
    # if you're a low admin
    if not utils.checkUserPermissions(environ['user'], 2):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    for origin in ['main', 'missionMaker']:
        if origin == 'main':
            missionDirPrefix = utils.missionMainDir
            toBeDeletedProperty = 'toBeDeletedMain'
            existsProperty = 'existsOnMain'
        else:
            missionDirPrefix = utils.missionMakerDir
            toBeDeletedProperty = 'toBeDeletedMM'
            existsProperty = 'existsOnMM'

        c.execute('''select * from versions where ''' + toBeDeletedProperty +
                  ''' = 1''')
        toBeDeleted = c.fetchall()
        for deleteMe in toBeDeleted:
            try:
                os.remove(os.path.join(missionDirPrefix, deleteMe['name']))
            except OSError:
                pass

        c.execute("update versions set " + existsProperty + " = 0, " +
                  toBeDeletedProperty + " = 0 where " + toBeDeletedProperty +
                  " = 1")
    c.execute(
        "SELECT id FROM versions WHERE existsOnMM = 0 AND existsOnMain = 0")
    versionRowsToBeDeleted = c.fetchall()
    ids = [str(x['id']) for x in versionRowsToBeDeleted]
    idParameter = ",".join(ids)
    c.execute(
        str.format('''DELETE FROM comments WHERE versionId IN ({})''',
                   idParameter))

    c.execute("delete from versions where existsOnMM = 0 and existsOnMain = 0")
    c.connection.commit()
    c.connection.close()

    start_response("200 OK", [])
    return []
Пример #12
0
def handleArchive(environ, start_response):
    c = utils.getCursor()
    missionJsonString = utils.environToContents(environ)
    missionJson = json.loads(missionJsonString)
    missionId = missionJson['missionId']
    versionId = missionJson['versionId']
    origin = missionJson['origin']
    # if you're a low admin or this is your mission
    if not utils.checkUserPermissions(environ['user'], 2, missionId):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    if origin == 'main':
        property = 'toBeArchivedMain'
    else:
        property = 'toBeArchivedMM'

    c.execute('''update versions set ''' + property + ''' = 1 where id = ?''',
              [versionId])
    c.connection.commit()
    c.connection.close()
    start_response("200 OK", [])
    return []
Пример #13
0
def handleSync(environ, start_response):
    c = utils.getCursor()
    if utils.checkUserPermissions(environ['user'], 3):

        c.execute(str.format('''select * from versions order by missionId'''))
        versionsFromDb = c.fetchall()

        for version in versionsFromDb:
            existsOnMM = False
            if version['existsOnMM']:
                existsOnMM = True
                if not Path(utils.missionMakerDir + "/" + version['name']).is_file():
                    existsOnMM = False
                    c.execute(str.format('''update versions set existsOnMM=0 where id = {}''', version['id']))

            existsOnMain = False
            if version['existsOnMain']:
                existsOnMain = True
                if not Path(utils.missionMainDir + "/" + version['name']).is_file():
                    existsOnMain = False
                    c.execute(str.format('''update versions set existsOnMain=0 where id = {}''', version['id']))

            if not existsOnMain and not existsOnMM:
                c.execute(str.format('''delete from versions where id = {}''', version['id']))

        c.connection.commit()
        c.connection.close()

        c = utils.getCursor()

        c.execute('''select id, missionName from missions''')

        missions = c.fetchall()
        fileNames = os.listdir(utils.missionMakerDir)

        filesGroupedByMissionName = {}
        for k, g in itertools.groupby(fileNames, lambda x: sanatizeFileName(x)):
            filesGroupedByMissionName[k] = list(g)

        c.execute('''select name from versions''')
        versionRows = c.fetchall()
        versions = [x['name'] for x in versionRows]

        # for each db mission
        # find all files that match
        # for each file
        # find out if file is in db
        # if not
        # add to db
        for mission in missions:
            sanitizedName = sanatizeMissionName(mission['missionName'])
            if sanitizedName in filesGroupedByMissionName:

                filesForThisMission = filesGroupedByMissionName[sanitizedName]
                for fileForThisMission in filesForThisMission:
                    if not fileForThisMission in versions:
                        c.execute(
                            "insert into versions(missionId, name, createDate) values (?, ?, ?)",
                            [mission['id'], fileForThisMission, date.today()])

                    c.execute("update versions set existsOnMM = 1 where name = ?", [fileForThisMission])

        c.connection.commit()
        c.connection.close()

        c = utils.getCursor()

        fileNames = os.listdir(utils.missionMainDir)

        filesGroupedByMissionName = {}
        for k, g in itertools.groupby(fileNames, lambda x: sanatizeFileName(x)):
            filesGroupedByMissionName[k] = list(g)

        c.execute('''select name from versions''')
        versionRows = c.fetchall()
        versions = [x['name'] for x in versionRows]

        # for each db mission
        # find all files that match
        # for each file
        # find out if file is in db
        # if not
        # add to db
        for mission in missions:
            sanitizedName = sanatizeMissionName(mission['missionName'])
            if sanitizedName in filesGroupedByMissionName:

                filesForThisMission = filesGroupedByMissionName[sanitizedName]
                for fileForThisMission in filesForThisMission:
                    if not fileForThisMission in versions:
                        c.execute(
                            "insert into versions(missionId, name, createDate, existsOnMM) values (?, ?, ?, ?)",
                            [mission['id'], fileForThisMission, date.today(), False])
                    c.execute("update versions set existsOnMain = 1 where name = ?", [fileForThisMission])

        c.connection.commit()
        c.connection.close()


    else:
        start_response("403 Permission Denied", [])
        return ["Access Denied".encode()]

    start_response("200 OK", [])
    return []
Пример #14
0
def handleUpload(environ, start_response):
    c = utils.getCursor()
    o = parse_qs(environ['QUERY_STRING'])
    missionId = o['missionId'][0]
    if not utils.checkUserPermissions(environ['user'], 2, missionId):
        start_response("403 Permission Denied", [])
        return ["Access Denied"]

    # This monstrosity of code was copied from the internet, I barely understand how it works

    content_type = environ.get('CONTENT_TYPE', '0')
    if not content_type:
        start_response("500 Internal Server Error", [])
        return ["Content-Type header doesn't contain boundary".encode()]
    boundary = content_type.split("=")[1].encode()
    remainbytes = int(environ.get('CONTENT_LENGTH', '0'))

    if remainbytes > (20 * 1024 * 1024):
        start_response("500 Internal Server Error", [])
        return ["20 MB is the max size".encode()]

    line = environ['wsgi.input'].readline()
    remainbytes -= len(line)
    if not boundary in line:
        start_response("500 Internal Server Error", [])
        return ["Content NOT begin with boundary".encode()]
    line = environ['wsgi.input'].readline()
    remainbytes -= len(line)
    decode = line.decode()
    regex = r'Content-Disposition.*name="upload_file"; filename="(.*)".*'
    fn = re.findall(regex, decode)
    if not fn:
        start_response("500 Internal Server Error", [])
        return ["Can't find out file name...".encode()]

    fileName = fn[0]

    # protect from filesystem roaming
    fileName = fileName.replace("..", "")

    if not fileName.endswith(".pbo"):
        start_response("500 Internal Server Error", [])
        return ["Only .pbo files are allowed".encode()]

    fullPath = os.path.join(utils.missionMakerDir, fileName).replace("\n", "")
    line = environ['wsgi.input'].readline()
    remainbytes -= len(line)
    line = environ['wsgi.input'].readline()
    remainbytes -= len(line)
    try:
        out = open(fullPath, 'wb')
    except IOError:
        start_response("500 Internal Server Error", [])
        return ["Can't create file to write, do you have permission to write?".encode()]

    preline = environ['wsgi.input'].readline()
    remainbytes -= len(preline)
    while remainbytes > 0:
        line = environ['wsgi.input'].readline()
        remainbytes -= len(line)
        if boundary in line:
            preline = preline[0:-1]
            if preline.endswith(b'\r'):
                preline = preline[0:-1]
            out.write(preline)
            out.close()
        else:
            out.write(preline)
            preline = line

    # rest of the properties are set by defaults in the table
    c.execute(
        "INSERT INTO versions(missionId, name, createDate) VALUES (?, ?, ?)",
        [missionId, fileName, date.today()])
    c.connection.commit()
    c.connection.close()

    start_response("200 OK", [])
    return ["success".encode()]