Beispiel #1
0
    def mark_as_teacher():
        if not is_admin(request):
            return 'unauthorized', 403

        body = request.json

        # Validations
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if not object_check(body, 'username', 'str'):
            return 'body.username must be a string', 400
        if not object_check(body, 'is_teacher', 'bool'):
            return 'body.is_teacher must be boolean', 400

        user = db_get('users', {'username': body['username'].strip().lower()})

        if not user:
            return 'invalid username', 400

        db_update(
            'users', {
                'username': user['username'],
                'is_teacher': 1 if body['is_teacher'] else 0
            })

        return '', 200
Beispiel #2
0
    def verify_email():
        username = request.args.get('username', None)
        token = request.args.get('token', None)
        if not token:
            return 'no token', 400
        if not username:
            return 'no username', 400

        user = db_get('users', {'username': username})

        if not user:
            return 'invalid username/token', 403

        # If user is verified, succeed anyway
        if not 'verification_pending' in user:
            return redirect('/')

        if token != user['verification_pending']:
            return 'invalid username/token', 403

        db_update('users', {
            'username': username,
            'verification_pending': None
        })
        return redirect('/')
Beispiel #3
0
    def reset():
        body = request.json
        # Validations
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if not object_check(body, 'username', 'str'):
            return 'body.username must be a string', 400
        if not object_check(body, 'token', 'str'):
            return 'body.token must be a string', 400
        if not object_check(body, 'password', 'str'):
            return 'body.password be a string', 400

        if len(body['password']) < 6:
            return 'password must be at least six characters long', 400

        # There's no need to trim or lowercase username, because it should come within a link prepared by the app itself and not inputted manually by the user.
        token = db_get('tokens', {'id': body['username']})
        if not token:
            return 'invalid username/token', 403
        if not check_password(body['token'], token['token']):
            return 'invalid username/token', 403

        hashed = hash(body['password'], make_salt())
        token = db_del('tokens', {'id': body['username']})
        db_update('users', {'username': body['username'], 'password': hashed})
        user = db_get('users', {'username': body['username']})

        if not is_testing_request(request):
            send_email_template('reset_password', user['email'],
                                requested_lang(), None)

        return '', 200
Beispiel #4
0
    def login():
        body = request.json
        # Validations
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if not object_check(body, 'username', 'str'):
            return 'username must be a string', 400
        if not object_check(body, 'password', 'str'):
            return 'password must be a string', 400

        # If username has an @-sign, then it's an email
        if '@' in body['username']:
            user = db_get('users', {'email': body['username'].strip().lower()},
                          True)
        else:
            user = db_get('users',
                          {'username': body['username'].strip().lower()})

        if not user:
            return 'invalid username/password', 403
        if not check_password(body['password'], user['password']):
            return 'invalid username/password', 403

        # If the number of bcrypt rounds has changed, create a new hash.
        new_hash = None
        if config['bcrypt_rounds'] != extract_bcrypt_rounds(user['password']):
            new_hash = hash(body['password'], make_salt())

        cookie = make_salt()
        db_create(
            'tokens', {
                'id': cookie,
                'username': user['username'],
                'ttl': times() + session_length
            })
        if new_hash:
            db_update(
                'users', {
                    'username': user['username'],
                    'password': new_hash,
                    'last_login': timems()
                })
        else:
            db_update('users', {
                'username': user['username'],
                'last_login': timems()
            })
        resp = make_response({})
        # We set the cookie to expire in a year, just so that the browser won't invalidate it if the same cookie gets renewed by constant use.
        # The server will decide whether the cookie expires.
        resp.set_cookie(cookie_name,
                        value=cookie,
                        httponly=True,
                        secure=True,
                        samesite='Lax',
                        path='/',
                        max_age=365 * 24 * 60 * 60)
        return resp
Beispiel #5
0
def save_program(user):

    body = request.json
    if not type_check(body, 'dict'):
        return 'body must be an object', 400
    if not object_check(body, 'code', 'str'):
        return 'code must be a string', 400
    if not object_check(body, 'name', 'str'):
        return 'name must be a string', 400
    if not object_check(body, 'level', 'int'):
        return 'level must be an integer', 400
    if 'adventure_name' in body:
        if not object_check(body, 'adventure_name', 'str'):
            return 'if present, adventure_name must be a string', 400

    name = body['name']

    # We check if a program with a name `xyz` exists in the database for the username.
    # It'd be ideal to search by username & program name, but since DynamoDB doesn't allow searching for two indexes at the same time, this would require to create a special index to that effect, which is cumbersome.
    # For now, we bring all existing programs for the user and then search within them for repeated names.
    programs = db_get_many('programs', {'username': user['username']}, True)
    program = {}
    overwrite = False
    for program in programs:
        if program['name'] == name:
            overwrite = True
            break

    stored_program = {
        'id': program.get('id') if overwrite else uuid.uuid4().hex,
        'session': session_id(),
        'date': timems(),
        'lang': requested_lang(),
        'version': version(),
        'level': body['level'],
        'code': body['code'],
        'name': name,
        'username': user['username']
    }

    if 'adventure_name' in body:
        stored_program['adventure_name'] = body['adventure_name']

    if overwrite:
        db_update('programs', stored_program)
    else:
        db_create('programs', stored_program)

    program_count = 0
    if 'program_count' in user:
        program_count = user['program_count']
    db_update('users', {
        'username': user['username'],
        'program_count': program_count + 1
    })

    return jsonify({'name': name})
Beispiel #6
0
def delete_program (user, program_id):
    result = db_get ('programs', {'id': program_id})
    if not result or result ['username'] != user ['username']:
        return "", 404
    db_del ('programs', {'id': program_id})
    program_count = 0
    if 'program_count' in user:
        program_count = user ['program_count']
    db_update ('users', {'username': user ['username'], 'program_count': program_count - 1})
    return redirect ('/programs')
Beispiel #7
0
def check_task():
    '''
    检查任务
    '''
    #@tornado.web.authenticated
    now = datetime.datetime.now()
    now_date_s = now.strftime('%Y-%m-%d')
    print '---check_task start---', now
    #检查每日任务
    everyday_tasks = preload_b_e.find()
    for e_t in everyday_tasks:
        e_start_time = e_t['start_time']
        e_start_hour, e_start_min = e_start_time.split(':')
        if now.hour == int(e_start_hour) and now.minute == int(e_start_min):
            #创建定时任务
            resource_url = e_t['resource_url'].replace('$date', now_date_s)
            preload_b.insert({
                'username': e_t['username'],
                'start_datetime': now,
                'created_time': now,
                'resource_url': resource_url,
                'group_detail': e_t['group_detail'],
                'run_datetime': '',
                'finish_datetime': '',
                'concurrency': e_t['concurrency'],
                'e_id': e_t['_id']
            })

    tasks = preload_b.find({
        'run_datetime': "",
        "start_datetime": {
            "$lte": now
        }
    })
    to_run = []
    for task in tasks:
        task_id = task['_id']
        old_res = preload_b_result.find({'task_id': task_id}).count()
        #2次检查
        if old_res > 0:
            continue
        to_run.append(task)

    #print to_run

    for t in to_run:
        send(t)
        db_update(preload_b, {'_id': ObjectId(t['_id'])},
                  {"$set": {
                      "run_datetime": now
                  }})

    print '---check_task start over---'
Beispiel #8
0
    def post(self, task_id):
        login_name, authority = get_login_name(self)
        author_secure = get_login_author_secure(self)
        task = preload_b.find_one({'_id': ObjectId(task_id)})
        if not task:
            self.write(error_res('no task'))
            return

    # if task['run_datetime']:
    #     self.write(error_res('task had started'))
    #     return

        now = datetime.datetime.now()
        username = self.get_argument('username', '')
        start_datetime_str = self.get_argument('start_datetime', '')
        start_datetime = datetime.datetime.strptime(start_datetime_str,
                                                    '%Y-%m-%d %H:%M')
        #if start_datetime < now:
        #    raise
        resource_url = self.get_argument('resource_url', '')
        concurrency = int(self.get_argument('concurrency', 0))

        group_detail = []
        group_num = int(self.get_argument('group_num', 0))

        for g_n in xrange(group_num):
            new_g = g_n + 1
            clients = self.get_argument('%s-client' % (new_g))
            client_ips = clients.split('&')
            servers = self.get_argument('%s-server' % (new_g))
            server_ips = servers.split('&')
            group_detail.append([client_ips, server_ips])

        print '------TaskChange------'
        print username
        print start_datetime
        print resource_url
        print group_detail
        print concurrency
        print '------TaskChange over------'

        db_update(preload_b, {'_id': ObjectId(task_id)}, {
            '$set': {
                'username': username,
                'start_datetime': start_datetime,
                'resource_url': resource_url,
                'group_detail': group_detail,
                'concurrency': concurrency
            }
        })

        self.redirect('/tasks')
Beispiel #9
0
def share_unshare_program(user):
    body = request.json
    if not type_check (body, 'dict'):
        return 'body must be an object', 400
    if not object_check (body, 'id', 'str'):
        return 'id must be a string', 400
    if not object_check (body, 'public', 'bool'):
        return 'public must be a string', 400

    result = db_get ('programs', {'id': body ['id']})
    if not result or result ['username'] != user ['username']:
        return 'No such program!', 404

    db_update ('programs', {'id': body ['id'], 'public': 1 if body ['public'] else None})
    return jsonify({})
Beispiel #10
0
    def change_user_email():
        if not is_admin(request):
            return 'unauthorized', 403

        body = request.json

        # Validations
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if not object_check(body, 'username', 'str'):
            return 'body.username must be a string', 400
        if not object_check(body, 'email', 'str'):
            return 'body.email must be a string', 400
        if not valid_email(body['email']):
            return 'email must be a valid email', 400

        user = db_get('users', {'username': body['username'].strip().lower()})

        if not user:
            return 'invalid username', 400

        token = make_salt()
        hashed_token = hash(token, make_salt())

        # We assume that this email is not in use by any other users. In other words, we trust the admin to enter a valid, not yet used email address.
        db_update(
            'users', {
                'username': user['username'],
                'email': body['email'],
                'verification_pending': hashed_token
            })

        # If this is an e2e test, we return the email verification token directly instead of emailing it.
        if is_testing_request(request):
            resp = {'username': user['username'], 'token': hashed_token}
        else:
            send_email_template(
                'welcome_verify', body['email'], requested_lang(),
                os.getenv('BASE_URL') + '/auth/verify?username='******'username']) + '&token=' +
                urllib.parse.quote_plus(hashed_token))

        return '', 200
Beispiel #11
0
    def change_password(user):

        body = request.json
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if not object_check(body, 'old_password', 'str'):
            return 'body.old_password must be a string', 400
        if not object_check(body, 'new_password', 'str'):
            return 'body.new_password must be a string', 400

        if len(body['new_password']) < 6:
            return 'password must be at least six characters long', 400

        if not check_password(body['old_password'], user['password']):
            return 'invalid username/password', 403

        hashed = hash(body['new_password'], make_salt())

        db_update('users', {'username': user['username'], 'password': hashed})
        if not is_testing_request(request):
            send_email_template('change_password', user['email'],
                                requested_lang(), None)

        return '', 200
Beispiel #12
0
def save_program (user):

    body = request.json
    if not type_check (body, 'dict'):
        return 'body must be an object', 400
    if not object_check (body, 'code', 'str'):
        return 'code must be a string', 400
    if not object_check (body, 'name', 'str'):
        return 'name must be a string', 400
    if not object_check (body, 'level', 'int'):
        return 'level must be an integer', 400
    if 'adventure_name' in body:
        if not object_check (body, 'adventure_name', 'str'):
            return 'if present, adventure_name must be a string', 400

    # We execute the saved program to see if it would generate an error or not
    error = None
    try:
        hedy_errors = TRANSLATIONS.get_translations(requested_lang(), 'HedyErrorMessages')
        result = hedy.transpile(body ['code'], body ['level'])
    except hedy.HedyException as E:
        error_template = hedy_errors[E.error_code]
        error = error_template.format(**E.arguments)
    except Exception as E:
        error = str(E)

    name = body ['name']

    # If name ends with (N) or (NN), we strip them since it's very likely these addenda were added by our server to avoid overwriting existing programs.
    name = re.sub (' \(\d+\)$', '', name)
    # We check if a program with a name `xyz` exists in the database for the username. If it does, we exist whether `xyz (1)` exists, until we find a program `xyz (NN)` that doesn't exist yet.
    # It'd be ideal to search by username & program name, but since DynamoDB doesn't allow searching for two indexes at the same time, this would require to create a special index to that effect, which is cumbersome.
    # For now, we bring all existing programs for the user and then search within them for repeated names.
    existing = db_get_many ('programs', {'username': user ['username']}, True)
    name_counter = 0
    for program in existing:
        if re.match ('^' + re.escape (name) + '( \(\d+\))*', program ['name']):
            name_counter = name_counter + 1
    if name_counter:
        name = name + ' (' + str (name_counter) + ')'

    stored_program = {
        'id': uuid.uuid4().hex,
        'session': session_id(),
        'date': timems (),
        'lang': requested_lang(),
        'version': version(),
        'level': body ['level'],
        'code': body ['code'],
        'name': name,
        'server_error': error,
        'username': user ['username']
    }

    if 'adventure_name' in body:
        stored_program ['adventure_name'] = body ['adventure_name']

    db_create('programs', stored_program)

    program_count = 0
    if 'program_count' in user:
        program_count = user ['program_count']
    db_update('users', {'username': user ['username'], 'program_count': program_count + 1})

    return jsonify({'name': name})
Beispiel #13
0
    def update_profile(user):

        body = request.json
        if not type_check(body, 'dict'):
            return 'body must be an object', 400
        if 'email' in body:
            if not object_check(body, 'email', 'str'):
                return 'body.email must be a string', 400
            if not valid_email(body['email']):
                return 'body.email must be a valid email', 400
        if 'country' in body:
            if not body['country'] in countries:
                return 'body.country must be a valid country', 400
        if 'birth_year' in body:
            if not object_check(
                    body, 'birth_year',
                    'int') or body['birth_year'] <= 1900 or body[
                        'birth_year'] > datetime.datetime.now().year:
                return 'birth_year must be a year between 1900 and ' + str(
                    datetime.datetime.now().year), 400
        if 'gender' in body:
            if body['gender'] != 'm' and body['gender'] != 'f' and body[
                    'gender'] != 'o':
                return 'body.gender must be m/f/o', 400

        resp = {}
        if 'email' in body:
            email = body['email'].strip().lower()
            if email != user['email']:
                exists = db_get('users', {'email': email}, True)
                if exists:
                    return 'email exists', 403
                token = make_salt()
                hashed_token = hash(token, make_salt())
                db_update(
                    'users', {
                        'username': user['username'],
                        'email': email,
                        'verification_pending': hashed_token
                    })
                # If this is an e2e test, we return the email verification token directly instead of emailing it.
                if is_testing_request(request):
                    resp = {
                        'username': user['username'],
                        'token': hashed_token
                    }
                else:
                    send_email_template(
                        'welcome_verify', email, requested_lang(),
                        os.getenv('BASE_URL') + '/auth/verify?username='******'username']) + '&token=' +
                        urllib.parse.quote_plus(hashed_token))

        if 'country' in body:
            db_update('users', {
                'username': user['username'],
                'country': body['country']
            })
        if 'birth_year' in body:
            db_update('users', {
                'username': user['username'],
                'birth_year': body['birth_year']
            })
        if 'gender' in body:
            db_update('users', {
                'username': user['username'],
                'gender': body['gender']
            })

        return jsonify(resp)
Beispiel #14
0
    def post(self):

        _id = self.get_argument('conf_id', '')
        cycle = self.get_argument('cycle', 0)
        num = self.get_argument('num', 0)
        visit_cycle = self.get_argument('visit_cycle', 0)
        visit_num = self.get_argument('visit_num', 0)
        named_str = self.get_argument('named_map')
        rules_str = self.get_argument('rules_map')
        cache_invalid_time = cycle
        add_query_time = self.get_argument('add_query_time')
        all_query_time = self.get_argument('all_query_time')
        # if not cycle:
        #     return self.write(error_res('Please put cycle'))
        # if not num:
        #     return self.write(error_res('Please put num'))
        # if not visit_cycle:
        #     return self.write(error_res('Please put visit_cycle'))
        # if not visit_num:
        #     return self.write(error_res('Please put visit_num'))
        if rules_str:
            for line in rules_str.split('\n'):
                if len(line.split(',')) != 4:
                    return self.write(
                        error_res('Please enter the right rules_map'))
        if named_str:
            for line in named_str.split('\n'):
                if len(line.split(',')) != 5:
                    return self.write(
                        error_res('Please enter the right named_map'))
        # if not cache_invalid_time:
        #     return self.write(error_res('Please put cache_invalid_time'))
        if not add_query_time:
            return self.write(error_res('Please put add_query_time'))
        if not all_query_time:
            return self.write(error_res('Please put all_query_time'))
        cycle = 0 if not cycle else int(cycle)
        num = 0 if not num else int(num)
        visit_cycle = 0 if not visit_cycle else int(visit_cycle)
        visit_num = 0 if not visit_num else int(visit_num)
        cache_invalid_time = 0 if not cache_invalid_time else int(
            cache_invalid_time)
        add_query_time = int(add_query_time)
        all_query_time = int(all_query_time)
        if named_str:
            named_map = [{
                'named': i.split(',')[0].strip(),
                'locationName': i.split(',')[1].strip(),
                'namedCycle': int(i.split(',')[2].strip()),
                'namedNum': int(i.split(',')[3].strip()),
                'namedPeriod': int(i.split(',')[4].strip())
            } for i in named_str.split('\n')]
        else:
            named_map = []

        if rules_str:
            rules_map = [{
                'theKey': i.split(',')[0].strip(),
                'theCycle': int(i.split(',')[1].strip()),
                'theNum': int(i.split(',')[2].strip()),
                'thePeriod': int(i.split(',')[3].strip())
            } for i in rules_str.split('\n')]
        else:
            rules_map = []

        new_conf = {
            "cycle": cycle,
            "num": num,
            "visit_cycle": visit_cycle,
            "visit_num": visit_num,
            "cache_invalid_time": cache_invalid_time,
            "add_query_time": add_query_time,
            "all_query_time": all_query_time
        }
        if rules_map:
            new_conf.update({'rules_map': rules_map})
        if named_map:
            new_conf.update({'named_map': named_map})
        old_conf = control_conf.find_one({'_id': ObjectId(_id)})
        if not old_conf:
            return self.write(error_res('This config had already deleted'))

        try:
            db_update(control_conf, {'_id': ObjectId(_id)}, {'$set': new_conf})
        except Exception:
            logger.info('ConfigChangeExec[post][error]: %s' %
                        (traceback.format_exc(), ))
        else:
            logger.info(
                'ConfigChangeExec[post] channel: %s|| suffix: %s|| category: %s'
                % (old_conf['channel'], str(old_conf.get(
                    'suffix', '')), old_conf['category']))
            makeSthStrInDict(new_conf, 'rules_map')
            makeSthStrInDict(new_conf, 'named_map')
            add_config_cache(
                "%s%s" %
                (old_conf['channel'], str(old_conf.get('suffix', ''))),
                old_conf['category'], new_conf)

        self.redirect('/conf')
Beispiel #15
0
    def post(self):

        now = datetime.datetime.now()
        req = json.loads(self.request.body)
        remote_ip = self.request.remote_ip

        task_id = req.get('task_id', '')
        #fc ip
        server_ip = req.get('server_ip', '')
        success_num = req.get('success_num', '')
        error_num = req.get('error_num', '')
        num_404 = req.get('not_found_num', '')
        total_num = req.get('total_num', '')
        is_finish = req.get('is_finish', 'false')
        duration = int(req.get('duration', 0))

        print '---TaskApiUpdate---'
        print 'remote_ip', remote_ip
        print 'task_id', task_id
        print 'server_ip', server_ip
        print 'success_num', success_num
        print 'error_num', error_num
        print 'num_404', num_404
        print 'is_finish', is_finish
        print 'total_num', total_num
        print 'duration', duration
        print '---TaskApiUpdate---end'

        if not task_id:
            print 'no task_id'
            raise
        if not success_num and not error_num and not num_404:
            print 'no num'
            raise

        old_task = preload_b_result.find_one({
            'task_id': task_id,
            'client_ip': remote_ip,
            'server_ip': server_ip
        })
        if not old_task:
            raise

        if is_finish == 'true':
            db_update(preload_b_result, {
                'task_id': task_id,
                'client_ip': remote_ip,
                'server_ip': server_ip
            }, {
                "$set": {
                    'success_num': success_num,
                    'error_num': error_num,
                    'not_found_num': num_404,
                    'total_num': total_num,
                    'update_datetime': now,
                    'duration': duration
                }
            })
        else:
            db_update(preload_b_result, {
                'task_id': task_id,
                'client_ip': remote_ip,
                'server_ip': server_ip
            }, {
                "$set": {
                    'success_num': success_num,
                    'error_num': error_num,
                    'not_found_num': num_404,
                    'total_num': total_num,
                    'update_datetime': now
                }
            })

        all_finish = True
        for t in preload_b_result.find({'task_id': task_id}):
            if not t['duration']:
                all_finish = False
                break

        if all_finish:
            #总任务成功
            print task_id, 'all_finish', now
            db_update(preload_b, {
                '_id': ObjectId(task_id),
                'finish_datetime': ''
            }, {'$set': {
                'finish_datetime': now
            }})

        w = {}
        w['code'] = 200
        self.write(json.dumps(w))