Esempio n. 1
0
 def post_admin(self, data):
     cid = data.get('cid', None)
     tid = data.get('tid', None)
     if not cid or not tid:
         raise errors.ValidationError('Requires team and challenge.')
     challenge = models.Challenge.query.get(data['cid'])
     team = models.Team.query.get(data['tid'])
     if not challenge or not team:
         raise errors.ValidationError('Requires team and challenge.')
     user = models.User.current()
     app.challenge_log.info(
         'Admin %s <%s> submitting flag for challenge %s <%d>, '
         'team %s <%d>', user.nick, user.email, challenge.name,
         challenge.cid, team.name, team.tid)
     try:
         points = controllers.save_team_answer(challenge, team, None)
     except (errors.IntegrityError, errors.FlushError) as ex:
         app.logger.exception('Unable to save answer for %s/%s: %s',
                              str(data['tid']), str(data['tid']), str(ex))
         models.db.session.rollback()
         raise errors.AccessDeniedError(
             'Unable to save answer for team. See log for details.')
     cache.delete('cats/%d' % tid)
     cache.delete('scoreboard')
     return dict(points=points)
Esempio n. 2
0
    def put(self, user_id):
        if not flask.g.uid == user_id and not flask.g.admin:
            raise errors.AccessDeniedError('No access to that user.')
        user = models.User.query.get_or_404(user_id)
        data = flask.request.get_json()
        if utils.is_admin() and 'admin' in data:
            if data['admin'] and not user.admin:
                try:
                    user.promote()
                except AssertionError:
                    raise errors.ValidationError(
                        'Error promoting. Has player solved challenges?')
            else:
                user.admin = False
        if data.get('password'):
            user.set_password(data['password'])
        if utils.is_admin():
            user.nick = data['nick']
            if not app.config.get('TEAMS') and user.team:
                user.team.name = data['nick']

        try:
            models.commit()
        except AssertionError:
                raise errors.ValidationError(
                        'Error in updating user.  Details are logged.')
        return user
Esempio n. 3
0
def change_user_team(uid, team_tid, code):
    """Provide an interface for changing a user's team"""
    team = models.Team.query.get_or_404(team_tid)
    user = models.User.query.get_or_404(uid)

    old_team = user.team

    if code.lower() != team.code.lower():
        raise errors.ValidationError('Invalid team selection or team code')

    if team.tid == user.team_tid:
        raise errors.ValidationError('Changing to same team')

    app.logger.info('User %s switched to team %s from %s' %
                    (user.nick, team.name, old_team.name))
    user.team = team
    user.team_tid = team_tid
    flask.session['team'] = team_tid

    if old_team.players.count() == 0 and len(old_team.answers) == 0:
        app.logger.info('Removing team %s due to lack of players' %
                        old_team.name)
        models.db.session.delete(old_team)

    models.commit()
Esempio n. 4
0
 def verify_token(self, token, token_type='pwreset'):
     """Verify a user-specific token."""
     token = str(token)
     decoded = base64.urlsafe_b64decode(token)
     expires, mac = decoded.split(':')
     if float(expires) > time.time():
         raise errors.ValidationError('Expired token.')
     expected = self.get_token(token_type=token_type, expires=int(expires))
     if not utils.compare_digest(expected, token):
         raise errors.ValidationError('Invalid token.')
     return True
Esempio n. 5
0
 def post(self):
     """Register a new user."""
     if utils.is_logged_in():
         raise errors.ValidationError('Cannot register while logged in.')
     data = flask.request.get_json()
     if not data.get('nick', ''):
         raise errors.ValidationError('Need a player nick.')
     if (app.config.get('TEAMS') and not data.get('team_name', '') and not
             data.get('team_id', 0)):
         raise errors.ValidationError('Need a team name.')
     user = auth.register(flask.request)
     utils.session_for_user(user)
     return user
Esempio n. 6
0
    def post(self):
        data = flask.request.get_json()
        unlocked = data.get('unlocked', False)
        answer = utils.normalize_input(data['answer'])
        if not validators.IsValidator(data.get('validator', None)):
            raise errors.ValidationError('Invalid validator.')
        chall = models.Challenge.create(
            data['name'], data['description'], data['points'], '', unlocked,
            data.get('validator', validators.GetDefaultValidator()))
        validator = validators.GetValidatorForChallenge(chall)
        validator.change_answer(answer)
        if 'attachments' in data:
            chall.set_attachments(data['attachments'])
        if 'prerequisite' in data:
            chall.set_prerequisite(data['prerequisite'])
        if 'tags' in data:
            chall.set_tags(data['tags'])

        if unlocked and utils.GameTime.open():
            news = 'New challenge created: "%s"' % chall.name
            models.News.game_broadcast(message=news)

        models.commit()
        app.logger.info('Challenge %s created by %r.', chall,
                        models.User.current())
        return chall
Esempio n. 7
0
    def put(self, challenge_id):
        challenge = models.Challenge.query.get_or_404(challenge_id)
        data = flask.request.get_json()
        old_unlocked = challenge.unlocked
        for field in ('name', 'description', 'points', 'unlocked', 'weight'):
            setattr(challenge, field, data.get(field,
                                               getattr(challenge, field)))
        if 'validator' in data:
            if not validators.IsValidator(data['validator']):
                raise errors.ValidationError('Invalid validator.')
            challenge.validator = data['validator']
        if 'answer' in data and data['answer']:
            answer = utils.normalize_input(data['answer'])
            validator = validators.GetValidatorForChallenge(challenge)
            validator.change_answer(answer)
        if 'attachments' in data:
            challenge.set_attachments(data['attachments'])
        if 'prerequisite' in data:
            challenge.set_prerequisite(data['prerequisite'])
        else:
            challenge.prerequisite = ''
        if 'tags' in data:
            challenge.set_tags(data['tags'])
        if challenge.unlocked and not old_unlocked:
            news = 'Challenge "%s" unlocked!' % challenge.name
            models.News.game_broadcast(message=news)

        app.logger.info('Challenge %s updated by %r.', challenge,
                        models.User.current())

        models.commit()
        cache.clear()
        return challenge
Esempio n. 8
0
def get_required_field(name, verbose_name=None):
    """Retrieve a field or raise an error."""

    try:
        return flask.request.form[name]
    except KeyError:
        verbose_name = verbose_name or name
        raise errors.ValidationError('%s is a required field.' % verbose_name)
Esempio n. 9
0
def get_field(name, *args):
    data = flask.request.get_json()
    try:
        return data[name]
    except KeyError:
        if args:
            return args[0]
        raise errors.ValidationError(
            'Required field {} not given.'.format(name))
Esempio n. 10
0
 def delete(self, category_slug):
     category = models.Category.query.get_or_404(category_slug)
     try:
         models.db.session.delete(category)
         cache.clear()
         models.commit()
     except exc.IntegrityError:
         models.db.session.rollback()
         raise errors.ValidationError(
             'Unable to delete category: make sure it is empty')
Esempio n. 11
0
def register_user(email, nick, password, team_id=None,
                  team_name=None, team_code=None):
    """Registers a player.

    Arguments:
      email: User's email
      nick: User's nick
      password: Player's password
      password2: Validation of password
      team_id: Id# of team, or None to create new team.
      team_name: Name of new team.
      team_code: Validation code to join team.
    """
    if not re.match(r'[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}$',
                    email):
        raise errors.ValidationError('Invalid email address.')
    first = models.User.query.count() == 0
    if not first and app.config.get('TEAMS'):
        if team_id == 'new':
            try:
                app.logger.info('Creating new team %s for user %s',
                        team_name, nick)
                team = models.Team.create(team_name)
            except exc.IntegrityError:
                models.db.session.rollback()
                raise errors.ValidationError('Team already exists!')
        else:
            team = models.Team.query.get(int(team_id))
            if not team or team_code.lower() != team.code.lower():
                raise errors.ValidationError(
                    'Invalid team selection or team code.')
    else:
        team = None
    try:
        if not team and not first:
            team = models.Team.create(nick)
        user = models.User.create(email, nick, password, team=team)
    except exc.IntegrityError:
        models.db.session.rollback()
        raise errors.ValidationError('Duplicate email/nick.')
    app.logger.info('User %s <%s> registered from IP %s.',
                    nick, email, flask.request.access_route[0])
    return user
Esempio n. 12
0
def register_user(email,
                  nick,
                  password,
                  team_id=None,
                  team_name=None,
                  team_code=None):
    """Registers a player.

    Arguments:
      email: User's email
      nick: User's nick
      password: Player's password
      team_id: Id# of team, or None to create new team.
      team_name: Name of new team.
      team_code: Validation code to join team.
    """
    if not re.match(r'[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]+$', email):
        raise errors.ValidationError('Invalid email address.')
    # TODO: Sanitize other fields
    first = models.User.query.count() == 0
    if not first and app.config.get('TEAMS'):
        if team_id == 'new':
            try:
                app.logger.info('Creating new team %s for user %s', team_name,
                                nick)
                team = models.Team.create(team_name)
            except exc.IntegrityError:
                models.db.session.rollback()
                raise errors.ValidationError('Team already exists!')
        else:
            team = models.Team.query.get(int(team_id))
            if not team or team_code.lower() != team.code.lower():
                raise errors.ValidationError(
                    'Invalid team selection or team code.')
    else:
        team = None
    try:
        if not team and not first:
            team = models.Team.create(nick)
        user = models.User.create(email, nick, password, team=team)
        models.commit()
    except exc.IntegrityError:
        models.db.session.rollback()
        if models.User.get_by_email(email):
            raise errors.ValidationError('Duplicate email address.')
        if models.User.get_by_nick(nick):
            raise errors.ValidationError('Duplicate nick.')
        if team_name and models.Team.get_by_name(team_name):
            raise errors.ValidationError('Duplicate team name.')
        raise errors.ValidationError('Unknown integrity error.')
    if not user.admin:
        models.ScoreHistory.add_entry(team)
        models.commit()
    app.logger.info('User %s <%s> registered from IP %s.', nick, email,
                    flask.request.remote_addr)
    return user
Esempio n. 13
0
 def post(self):
     """Register a new user."""
     if utils.is_logged_in():
         raise errors.ValidationError('Cannot register while logged in.')
     data = flask.request.get_json()
     if not data.get('nick', ''):
         raise errors.ValidationError('Need a player nick.')
     if (app.config.get('TEAMS') and not data.get('team_name', '')
             and not data.get('team_id', 0)):
         app.logger.warning('User attempted to register without team.')
         raise errors.ValidationError('Need a team name.')
     if (app.config.get('INVITE_KEY') and data.get(
             'invite_key', '').strip() != app.config.get('INVITE_KEY')):
         app.logger.warning(
             'Attempted invite-only registration with invalid '
             'invite key: %s', data.get('invite_key', ''))
         raise errors.ValidationError('Invalid invite key!')
     app.logger.debug('Passed registration validation for new user.')
     user = auth.register(flask.request)
     utils.session_for_user(user)
     return user
Esempio n. 14
0
 def post(self):
     """Register a new user."""
     if flask.g.user:
         raise errors.ValidationError('Cannot register while logged in.')
     data = flask.request.get_json()
     user = controllers.register_user(data['email'], data['nick'],
                                      data['password'], data.get(
                                          'team_id'), data.get('team_name'),
                                      data.get('team_code'))
     models.commit()
     flask.session['user'] = user.uid
     return user
Esempio n. 15
0
 def post(self, email):
     """Verify reset and set new password."""
     # TODO: Move to controller
     data = flask.request.get_json()
     user = models.User.get_by_email(email)
     if not user:
         flask.abort(404)
     if not user.verify_token(data.get('token', '')):
         raise errors.AccessDeniedError('Invalid token.')
     if data['password'] != data['password2']:
         raise errors.ValidationError("Passwords don't match.")
     user.set_password(data['password'])
     models.commit()
     controllers.user_login(email, data['password'])
     return {'message': 'Password reset.'}
Esempio n. 16
0
 def post(self, email):
     """Verify reset and set new password."""
     # TODO: Move to controller
     data = flask.request.get_json()
     user = models.User.get_by_email(email)
     if not user:
         flask.abort(404)
     token = data.get('token', '')
     try:
         user.verify_token(token)
     except errors.ValidationError as ex:
         app.logger.warning('Error validating password reset: %s', str(ex))
         raise
     except Exception as ex:
         app.logger.exception(
             'Unhandled exception during password reset: %s', str(ex))
         raise
     if data['password'] != data['password2']:
         raise errors.ValidationError("Passwords don't match.")
     user.set_password(data['password'])
     app.logger.info('Password reset for %r.', user)
     models.commit()
     utils.session_for_user(user)
     return {'message': 'Password reset.'}