def post(self):
        logging.info("[TASK] UserUpdateFirebaseHandler")

        key_id = self.request.get('key_id')

        user = UsersController().get_by_key_id(int(key_id))
        if not user:
            logging.error('User not found')
            return

        user_json = json.dumps(user.to_json() )

        credentials = GoogleCredentials.get_application_default().create_scoped(_FIREBASE_SCOPES)
        http_auth = credentials.authorize(Http())

        headers = {"Content-Type": "application/json"}
        URL = "%s/users/%s.json" % (FIREBASE_DATABASE_ROOT, user.firebaseUser)
        resp, content = http_auth.request(URL,
                            "PUT",
                          ##"PUT", ## Write or replace data to a defined path,
                          user_json,
                          headers=headers)

        logging.info(resp)
        logging.info(content)
Exemple #2
0
    def create(self, request):
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(
            ' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = RegionResponse(response_message='Firebase Unauth.',
                                      response_successful=False)
            return response

        authorized_user = UsersController().get_by_firebaseUser(
            claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return SeasonResponse(
                response_message='Error: No User Record Found. ',
                response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return SeasonResponse(
                response_message='Error: No Admin Record Found. ',
                response_successful=False)

        region = RegionsController().create(
            description=request.description,
            title=request.title,
            datacenter_location=request.datacenter_location)
        """
        credentials = AppAssertionCredentials(
            'https://www.googleapis.com/auth/sqlservice.admin')

        http_auth = credentials.authorize(Http())

        model_json = json.dumps(region.to_json())

        #logging.info(model_json)
        headers = {"Content-Type": "application/json"}

        URL = "%s/regions/%s.json" % (FIREBASE_DATABASE_ROOT, region.key.id() )
        logging.info(URL)
        resp, content = http_auth.request(URL,
                          "PUT", ## Write or replace data to a defined path,
                          model_json,
                          headers=headers)
        """

        #logging.info(resp)
        #logging.info(content)

        return RegionResponse(response_message="Region Created",
                              response_successful=True)
Exemple #3
0
    def update(self, request):
        logging.info('update')
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = SeasonResponse(
                response_message='Firebase Unauth.',
                response_successful=False
            )
            return response

        authorized_user = UsersController().get_by_firebaseUser(claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return SeasonResponse(response_message='Error: No User Record Found. ', response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return SeasonResponse(response_message='Error: No Admin Record Found. ', response_successful=False)

        startdate = dateutil.parser.parse(request.starts)
        enddate = dateutil.parser.parse(request.ends)

        ## get the model

        seasonController = SeasonsController()

        season=seasonController.get_by_key_id(int(request.key_id))
        if not season:
            logging.error('season not found')
            return SeasonResponse(response_message="Season Not Found", response_successful=False)

        season.description = request.description
        season.title = request.title
        season.starts = startdate
        season.ends = enddate
        season.active = request.active
        season.closing = request.closing
        season.next = request.next
        season.currentRound = request.currentRound
        season.currentRoundPositioning = request.currentRoundPositioning
        season.currentRoundCombat = request.currentRoundCombat
        season.currentRoundResults = request.currentRoundResults

        seasonController.update(season)

        if request.active:
            taskUrl='/task/season/firebase/update'
            taskqueue.add(url=taskUrl, queue_name='firebaseUpdate', params={'key_id': season.key.id()}, countdown = 2,)

        return SeasonResponse(response_message="Season Updated")
Exemple #4
0
    def create(self, request):
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = SeasonResponse(
                response_message='Firebase Unauth.',
                response_successful=False
            )
            return response

        authorized_user = UsersController().get_by_firebaseUser(claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return SeasonResponse(response_message='Error: No User Record Found. ', response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return SeasonResponse(response_message='Error: No Admin Record Found. ', response_successful=False)


        startdate = dateutil.parser.parse(request.starts)
        enddate = dateutil.parser.parse(request.ends)

        season=SeasonsController().create(
            description = request.description,
            title = request.title,
            starts = startdate,
            ends = enddate,
            active = request.active,
            currentRound = 0,
            currentRoundPositioning = True,
            currentRoundCombat = False,
            currentRoundResults = False
        )

        ## we need this on firebase to show the current state of the season.
        if request.active:
            taskUrl='/task/season/firebase/update'
            taskqueue.add(url=taskUrl, queue_name='firebaseUpdate', params={'key_id': season.key.id()}, countdown = 2,)


            if AUTOMATIC_PHASE_CHANGE:
                ## requeue the task based on settings in config
                logging.info('starting phase change task')

                taskUrl='/task/season/stage_change'
                taskqueue.add(url=taskUrl, queue_name='seasonStageChange', countdown = ROUND_DURATION_POSITIONING,)

        return SeasonResponse(response_message="Season Created",response_successful=True)
Exemple #5
0
    def mapCollectionGet(self, request):
        """ Get a collection of maps """
        logging.info("mapCollectionGet")

        # Verify Firebase auth.
        #logging.info(self.request_state)
        try:
            id_token = self.request_state.headers['x-metagame-auth'].split(
                ' ').pop()
        except:
            logging.error('Missing JWT')
            return MapCollection(
                response_message='Error: Authentication Token Missing.',
                response_successful=False)

        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            logging.error('Firebase Unauth')
            return MapCollection(
                response_message='Error: Firebase Authentication Missing.',
                response_successful=False)

        authorized_user = UsersController().get_by_firebaseUser(
            claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return MapCollection(
                response_message='Error: No User Record Found. ',
                response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return MapCollection(
                response_message='Error: No Admin Record Found. ',
                response_successful=False)

        mapController = MapsController()

        entities = mapController.list_by_regionKeyId(request.regionKeyId)
        entity_list = []

        for entity in entities:
            entity_list.append(
                MapResponse(key_id=entity.key.id(),
                            title=entity.title,
                            created=entity.created.isoformat()))

        response = MapCollection(maps=entity_list, response_successful=True)

        return response
Exemple #6
0
    def get(self, request):
        logging.info('get')
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = SeasonResponse(
                response_message='Firebase Unauth.',
                response_successful=False
            )
            return response

        authorized_user = UsersController().get_by_firebaseUser(claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return SeasonResponse(response_message='Error: No User Record Found. ', response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return SeasonResponse(response_message='Error: No Admin Record Found. ', response_successful=False)

        ## get the model

        seasonController = SeasonsController()

        season=seasonController.get_by_key_id(int(request.key_id))
        if not season:
            logging.error('season not found')
            return SeasonResponse(response_message="Season Not Found", response_successful=False)

        return SeasonResponse(
            key_id = season.key.id(),
            title = season.title,
            description = season.description,
            starts = season.starts.isoformat(),
            ends = season.ends.isoformat(),
            active = season.active,
            closing = season.closing,
            next = season.next,
            currentRound = season.currentRound,
            currentRoundPositioning = season.currentRoundPositioning,
            currentRoundCombat = season.currentRoundCombat,
            currentRoundResults = season.currentRoundResults,
            response_message="Season Updated")
    def post(self):
        """
        Recieve Notification when a player stops meta game mode
        Requires http headers:  Key, Sign
        Requires POST parameters:  nonce
        """

        ucontroller = UsersController()
        seasonsController = SeasonsController()
        factionController = FactionsController()
        zoneController = ZonesController()
        bidController = BidsController()

        ## make sure the API key matches first
        incomingApiKey = self.request.headers['Key']
        if incomingApiKey != UETOPIA_ASSIGNED_GAME_API_KEY:
            logging.info('API key mismatch')
            return self.render_json_response(
                authorization = False,
                request_successful = False
            )

        signature = self.request.headers['Sign']

        logging.info("request.body: %s" % self.request.body)
        logging.info("params: ")
        logging.info(self.request.arguments())
        logging.info("Headers: %s" %self.request.headers)

        sorted_params = self.request.body

        # Hash the params string to produce the Sign header value
        H = hmac.new(UETOPIA_ASSIGNED_GAME_API_SECRET, digestmod=hashlib.sha512)
        H.update(sorted_params)
        sign = H.hexdigest()

        logging.info("sign: %s" %sign)
        logging.info("Hsig: %s" %signature )

        if sign != signature:
            logging.info('signature mismatch')
            return self.render_json_response(
                authorization = False,
                request_successful = False
            )

        ## At this point, authorization was successful.  Continue with the call.
        logging.info('auth success')

        ## parse the json out of the body.
        jsonstring = self.request.body
        logging.info(jsonstring)
        jsonobject = json.loads(jsonstring)

        ## make sure we have the player, and that it matches one we have already connected
        if 'player_key_id' not in jsonobject:
            logging.info('Did not find player_key_id in json')

            return self.render_json_response(
                authorization = True,
                request_successful = False
            )

        user = ucontroller.get_by_uetopia_playerKeyId(jsonobject['player_key_id'])
        if not user:
            logging.info('user was not found.  make sure they connect to metagame first.')
            return self.render_json_response(
                authorization = True,
                request_successful = False
            )

        user.currentFactionKeyId = None
        user.currentFactionTag = None
        user.currentFactionLead = False
        user.currentFactionTeamLead = False

        ## update the user record.
        user.metaGameActive = False
        ucontroller.update(user)

        ## push out to firebase
        taskUrl='/task/user/firebase/update'
        taskqueue.add(url=taskUrl, queue_name='firebaseUpdate', params={'key_id': user.key.id()}, countdown = 2,)

        ## also update the zone if this user was controlling one.
        controlled_zone = zoneController.get_controlled_by_userCaptainKeyId(user.key.id())
        if controlled_zone:
            logging.info('found a zone this user was controlling')

            controlled_zone.controlled = False
            controlled_zone.factionKeyId = None
            controlled_zone.factionTag = None
            controlled_zone.userCaptainKeyId = None
            controlled_zone.userCaptainTitle = None
            controlled_zone.uetopiaGamePlayerKeyId = None
            controlled_zone.teamTitle = None

            zoneController.update(controlled_zone)

            ## don't bother updating the map here.

        ## also check for any bids that are pending.
        pending_bid = bidController.get_unprocessed_by_userKeyId(user.key.id())
        if pending_bid:
            logging.info('found a pending bid')

            ## maybe make it inactive or something more fancy if you want.  Just deleting it for now.
            bidController.delete(pending_bid)


        ## return status success so that uetopia knows the call worked.

        return self.render_json_response(
            authorization = True,
            request_successful=True
        )
Exemple #8
0
    def create(self, request):
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(
            ' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = SeasonResponse(response_message='Firebase Unauth.',
                                      response_successful=False)
            return response

        authorized_user = UsersController().get_by_firebaseUser(
            claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return MapResponse(
                response_message='Error: No User Record Found. ',
                response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return MapResponse(
                response_message='Error: No Admin Record Found. ',
                response_successful=False)

        ## Look up the season and region
        seasonController = SeasonsController()
        regionController = RegionsController()

        season = seasonController.get_by_key_id(request.seasonKeyId)
        if not season:
            logging.info('season not found by key')
            return MapResponse(response_message='Error: No Season Found. ',
                               response_successful=False)

        region = regionController.get_by_key_id(request.regionKeyId)
        if not region:
            logging.info('region not found by key')
            return MapResponse(response_message='Error: No Region Found. ',
                               response_successful=False)

        map = MapsController().create(
            description=request.description,
            title=request.title,
            seasonKeyId=season.key.id(),
            seasonTitle=season.title,
            seasonActive=season.active,
            regionKeyId=region.key.id(),
            regionTitle=region.title,
            regionDatacenterLocation=region.datacenter_location,
            zoneCountHorizontal=request.zoneCountHorizontal,
            zoneCountVertical=request.zoneCountVertical)
        """
        credentials = AppAssertionCredentials(
            'https://www.googleapis.com/auth/sqlservice.admin')

        http_auth = credentials.authorize(Http())

        model_json = json.dumps(model.to_json())

        #logging.info(model_json)
        headers = {"Content-Type": "application/json"}

        URL = "https://ue4topia.firebaseio.com/regions/%s.json" % model.key.id()
        resp, content = http_auth.request(URL,
                          "PUT", ## Write or replace data to a defined path,
                          model_json,
                          headers=headers)

        """
        #logging.info(resp)
        #logging.info(content)

        return MapResponse(response_message="Map Created",
                           response_successful=True)
    def post(self):
        logging.info("[TASK] SeasonStageChangeHandler")

        ## just use the active season
        #key_id = self.request.get('key_id')

        mapController = MapsController()
        zoneController = ZonesController()
        bidController = BidsController()
        seasonController = SeasonsController()
        factionsController = FactionsController()
        matchController = MatchController()
        usersController = UsersController()

        season = seasonController.get_active()
        if not season:
            logging.error('Season not found')
            return

        if not season.active:
            logging.error('Season not active')
            return

        ## Keep track of any factions that need bids refunded.
        refunding_faction_key_id_list = []

        ## which stage are we currently on?
        if season.currentRoundPositioning:
            logging.info('currentRoundPositioning')

            ## - GO through each map
            ## - - Go through each zone
            ## - - - Find the high bid, timestamp if equal
            ## - - - Refund all other bids
            ## - - - - mark it as not high bid, add the faction to the task list, and process all refunds in a separate task for ech faction separately.
            ## - - - High bids with a defender - Fire off API call to start the match
            ## - - - Otherwise, team/faction/user takes control of the cell.
            ## - - Update the map
            ## Update the Season

            ##  - Go through each map
            maps_for_this_season = mapController.list_by_seasonKeyId(
                season.key.id())

            for map in maps_for_this_season:
                logging.info('processing map: %s' % map.title)

                zones = zoneController.list_by_mapKeyId(map.key.id())

                for zone in zones:
                    logging.info('processing zone: %s' % zone.title)

                    ## get bids in reverse chrono - this way OLDER greater or equal bids can always push out NEWER bids
                    bids = bidController.list_by_zoneKeyId(zone.key.id())
                    logging.info('found %s bids' % len(bids))

                    if len(bids) > 0:
                        high_bid = None
                        high_bid_amount = 0

                        ## This is a little confusing.
                        ## We are checking if the bid in the loop is greater than the previous
                        ## If it is, we are marking this one as "highest" - marking the previous as "not highest" and "processed"
                        ## if it's not, we mark it as "processed" so it can get picked up in the faction refund task

                        for bid in bids:
                            if bid.bidAmount >= high_bid_amount:
                                logging.info('found new high bid')
                                # if there is a previous high bid, mark it as not high bid anymore
                                if high_bid:
                                    logging.info(
                                        'marking previous high bid processed')
                                    high_bid.highBid = False
                                    high_bid.bidProcessed = True

                                ## add the faction key to the list, if it's not already there
                                if bid.factionKeyId not in refunding_faction_key_id_list:
                                    refunding_faction_key_id_list.append(
                                        bid.factionKeyId)

                                bid.highBid = True
                                bid.bidProcessed = True

                                high_bid = bid
                                high_bid_amount = bid.bidAmount
                            else:
                                logging.info('found a lower bid')
                                bid.highBid = False
                                bid.bidProcessed = True

                                ## add the faction key to the list, if it's not already there
                                if bid.factionKeyId not in refunding_faction_key_id_list:
                                    refunding_faction_key_id_list.append(
                                        bid.factionKeyId)

                        # save
                        for bid in bids:
                            bidController.update(bid)

                        ## Now we have the highest bid in the high_bid variable
                        ## does this zone have a defender?
                        if zone.controlled:
                            logging.info('this zone is controlled')

                            ## also make sure that the defender is still active.  They may have gone offline or something
                            defending_user_captain = usersController.get_by_key_id(
                                zone.userCaptainKeyId)
                            if defending_user_captain and defending_user_captain.metaGameActive:
                                logging.info('defender is still online')

                                ## Create a match record for this, associate with teams factions and zone.
                                match = matchController.create(
                                    title=zone.title,
                                    zoneKeyId=zone.key.id(),
                                    zoneTitle=zone.title,
                                    mapKeyId=zone.mapKeyId,
                                    mapTitle=zone.mapTitle,
                                    seasonKeyId=zone.seasonKeyId,
                                    seasonTitle=zone.seasonTitle,
                                    regionKeyId=zone.regionKeyId,
                                    regionTitle=zone.regionTitle,
                                    regionDatacenterLocation=zone.
                                    regionDatacenterLocation,
                                    #defenderTeamKeyId = zone.,
                                    defenderTeamTitle=zone.teamTitle,
                                    defenderFactionKeyId=zone.factionKeyId,
                                    #defenderFactionTitle = zone.,
                                    defenderFactionTag=zone.factionTag,
                                    defenderUserKeyId=zone.userCaptainKeyId,
                                    defenderUserTitle=zone.userCaptainTitle,
                                    defenderUetopiaGamePlayerKeyId=zone.
                                    uetopiaGamePlayerKeyId,
                                    attackerTeamKeyId=high_bid.teamKeyId,
                                    attackerTeamTitle=high_bid.teamTitle,
                                    attackerFactionKeyId=high_bid.factionKeyId,
                                    attackerFactionTitle=high_bid.factionTitle,
                                    attackerFactionTag=high_bid.factionTag,
                                    attackerUserKeyId=high_bid.userKeyId,
                                    attackerUserTitle=high_bid.userTitle,
                                    attackerUetopiaGamePlayerKeyId=high_bid.
                                    uetopiaGamePlayerKeyId,
                                    active=True,
                                    verified=False,
                                    expired=False,
                                )

                                ## TODO - fire matchmaker API call

                                uri = "/api/v1/game/metagame/match_begin"

                                params = OrderedDict([
                                    ("nonce", time.time()),
                                    ("encryption", "sha512"),
                                    ("attackingPlayerKeyId",
                                     match.attackerUetopiaGamePlayerKeyId),
                                    ("defendingPlayerKeyId",
                                     match.defenderUetopiaGamePlayerKeyId),
                                    #("gameModeKeyId", match.regionTitle),
                                    ("region", match.regionDatacenterLocation),
                                    ("metaMatchKeyId", match.key.id())
                                ])

                                params = urllib.urlencode(params)

                                # Hash the params string to produce the Sign header value
                                H = hmac.new(UETOPIA_ASSIGNED_GAME_API_SECRET,
                                             digestmod=hashlib.sha512)
                                H.update(params)
                                sign = H.hexdigest()

                                headers = {
                                    "Content-type":
                                    "application/x-www-form-urlencoded",
                                    "Key": UETOPIA_ASSIGNED_GAME_API_KEY,
                                    "Sign": sign
                                }

                                conn = httplib.HTTPSConnection(UETOPIA_API_URL)

                                conn.request("POST", uri, params, headers)
                                response = conn.getresponse()

                                #logging.info(response.read())

                                ## parse the response
                                jsonstring = str(response.read())
                                logging.info(jsonstring)
                                jsonobject = json.loads(jsonstring)

                                # do something with the response
                                if not jsonobject['request_successful']:
                                    logging.info(
                                        'the validation request was unsuccessful'
                                    )

                                    return

                                logging.info('validation was successful')

                            else:
                                logging.info('Defender was not online')

                                zone.controlled = True
                                zone.factionKeyId = bid.factionKeyId
                                zone.factionTag = bid.factionTag
                                zone.userCaptainKeyId = bid.userKeyId
                                zone.userCaptainTitle = bid.userTitle
                                zone.uetopiaGamePlayerKeyId = bid.uetopiaGamePlayerKeyId
                                zone.teamTitle = bid.teamTitle

                                # save
                                zoneController.update(zone)

                        else:
                            logging.info('Not controlled')

                            zone.controlled = True
                            zone.factionKeyId = bid.factionKeyId
                            zone.factionTag = bid.factionTag
                            zone.userCaptainKeyId = bid.userKeyId
                            zone.userCaptainTitle = bid.userTitle
                            zone.uetopiaGamePlayerKeyId = bid.uetopiaGamePlayerKeyId
                            zone.teamTitle = bid.teamTitle

                            # save
                            zoneController.update(zone)

                            # also update the user so we have the controlled map id

                ## Update Map
                ## push out to firebase
                taskUrl = '/task/map/firebase/update'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='firebaseUpdate',
                    params={'key_id': map.key.id()},
                    countdown=2,
                )

            ## update season
            season.currentRoundCombat = True
            season.currentRoundPositioning = False
            season.currentRoundResults = False

            # save
            seasonController.update(season)

            ## push out to firebase
            taskUrl = '/task/season/firebase/update'
            taskqueue.add(
                url=taskUrl,
                queue_name='firebaseUpdate',
                params={'key_id': season.key.id()},
                countdown=2,
            )

            ## start a task to process bids for each of the factions
            for factionKeyId in refunding_faction_key_id_list:
                taskUrl = '/task/faction/process_bids'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='factionProcessBids',
                    params={'key_id': factionKeyId},
                    countdown=2,
                )

            if AUTOMATIC_PHASE_CHANGE:
                ## requeue the task based on settings in config
                logging.info('requeueing task')

                taskUrl = '/task/season/stage_change'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='seasonStageChange',
                    countdown=ROUND_DURATION_COMBAT,
                )

        elif season.currentRoundCombat:
            logging.info('currentRoundCombat')

            ## Time has run out on the round.
            ## All games should be finished by now.
            ## Any unplayed matches result in the zone returning back to uncontrolled.

            ## There could potentially be a lot of matches, so we are going to batch these.
            ## appengine can only support a maximum query size of 1000, so by batching, we can bypass this limitation
            curs = Cursor()
            more = True

            while more:
                active_matches, curs, more = matchController.list_active_page(
                    start_cursor=curs)

                for match in active_matches:
                    logging.info('processing active match')
                    if match.verified:
                        logging.info('found verified match')

                        ## move the winning user/team/faction into the zone
                        zone = zoneController.get_by_key_id(match.zoneKeyId)
                        if zone:
                            zone.controlled = True
                            zone.factionKeyId = match.winningFactionKeyId
                            zone.factionTag = match.winningFactionTitle
                            zone.userCaptainKeyId = match.winningUserKeyId
                            zone.userCaptainTitle = match.winningUserTitle
                            zone.teamTitle = match.winningTeamTitle
                            zone.uetopiaGamePlayerKeyId = match.winningUetopiaGamePlayerKeyId
                            # save
                            zoneController.update(zone)

                        else:
                            logging.info('zone was not found!')

                    else:
                        logging.info('found expired match')

                        zone = zoneController.get_by_key_id(match.zoneKeyId)
                        if zone:
                            zone.controlled = False
                            zone.factionKeyId = None
                            zone.factionTag = None
                            zone.userCaptainKeyId = None
                            zone.userCaptainTitle = None
                            zone.teamTitle = None
                            zone.uetopiaGamePlayerKeyId = None
                            # save
                            zoneController.update(zone)

                        else:
                            logging.info('zone was not found!')

                    ## mark the match inactive/processed if you want to keep the data around for mining
                    ## in this example we are just going to delete it.
                    matchController.delete(match)

            ## then switch modes to results.
            logging.info('match processing complete.')

            ## update season
            season.currentRoundCombat = False
            season.currentRoundPositioning = False
            season.currentRoundResults = True

            # save
            seasonController.update(season)

            ## push out to firebase
            taskUrl = '/task/season/firebase/update'
            taskqueue.add(
                url=taskUrl,
                queue_name='firebaseUpdate',
                params={'key_id': season.key.id()},
                countdown=2,
            )

            if AUTOMATIC_PHASE_CHANGE:
                ## requeue the task based on settings in config
                logging.info('requeueing task')

                taskUrl = '/task/season/stage_change'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='seasonStageChange',
                    countdown=ROUND_DURATION_RESULTS,
                )

        else:
            logging.info('currentRoundResults')

            ## add up rewards for winning each zone, and add them into the facton record.
            ## TODO - allow building here, or some other action to utelize the materials.  build defenses or whatever.

            ##  - Go through each faction
            ##  - - Get all of the zones the faction controls
            ##  - - - sum up the changes
            ##  - Update the faction

            curs = Cursor()
            more = True

            while more:
                active_factions, curs, more = factionsController.list_active_season_page(
                    season.key.id(), start_cursor=curs)
                for faction in active_factions:
                    logging.info('processing faction')

                    ## get zones under this faction's control
                    controlled_zones = zoneController.list_by_factionKeyId(
                        faction.key.id())
                    for zone in controlled_zones:
                        logging.info('found controlled zone')

                        ## add values for this zone to the faction
                        faction.energy = faction.energy + zone.energy
                        faction.materials = faction.materials + zone.materials
                        faction.control = faction.control + zone.control

                    ## give every faction the defaults - even if they don't control any zones
                    faction.energy = faction.energy + FACTION_ROUND_ENERGY
                    faction.materials = faction.materials + FACTION_ROUND_MATERIALS
                    faction.control = faction.control + FACTION_ROUND_CONTROL

                    # save
                    factionsController.update(faction)

                    ## update firebase only if season is not over
                    if datetime.datetime.now() < season.ends:
                        taskUrl = '/task/faction/firebase/update'
                        taskqueue.add(
                            url=taskUrl,
                            queue_name='firebaseUpdate',
                            params={'key_id': faction.key.id()},
                            countdown=2,
                        )

            ## check to see if the season is over - if it is, calculate the winners, give rewards, something...
            ## if not, update the round number and switch modes to positioning.

            if datetime.datetime.now() > season.ends:
                logging.info('this season is over.  ')

                ## TODO - mark it final, give rewards etc.

                curs = Cursor()
                more = True
                winning_faction = None
                winner_found = False

                ## get the winning faction from local db - we need them all anyway to reset, so just get them all sorted by control
                while more:
                    logging.info('More is true')
                    factions, curs, more = factionsController.list_active_season_page_by_control(
                        season.key.id(), start_cursor=curs)

                    for faction in factions:
                        logging.info('found faction')
                        ## the first record is our winner.
                        if not winner_found:
                            logging.info('found winner')
                            winner_found = True
                            winning_faction = faction

                            ## get the faction leaders from local db
                            faction_leaders = usersController.list_factionLeaders(
                                faction.key.id())

                            ## divide up the materials points that the faction has accumulated among the faction leaders.
                            ## any remainder will be given to the first record found.

                            if len(faction_leaders):
                                logging.info(
                                    'found at least one faction leader')

                                materials_earned_for_each_leader = faction.materials / len(
                                    faction_leaders)
                                materials_remainder = faction.materials % len(
                                    faction_leaders)
                                logging.info(
                                    'materials_earned_for_each_leader: %s' %
                                    materials_earned_for_each_leader)
                                logging.info('materials_remainder: %s' %
                                             materials_remainder)

                                remainder_added = False

                                for faction_lead in faction_leaders:
                                    logging.info('found a faction lead')

                                    ## DO DROPS

                                    uri = "/api/v1/game/player/%s/drops/create" % faction_lead.uetopia_playerKeyId

                                    json_values = ({
                                        u'nonce':
                                        time.time(),
                                        u'encryption':
                                        "sha512",
                                        u'title':
                                        CURRENT_SEASON_WINNER_DROP['title'],
                                        u'description':
                                        CURRENT_SEASON_WINNER_DROP[
                                            'description'],
                                        u'uiIcon':
                                        CURRENT_SEASON_WINNER_DROP['uiIcon'],
                                        u'data':
                                        CURRENT_SEASON_WINNER_DROP['data']
                                    })

                                    entity_json = json.dumps(json_values)

                                    # Hash the params string to produce the Sign header value
                                    H = hmac.new(
                                        UETOPIA_ASSIGNED_GAME_API_SECRET,
                                        digestmod=hashlib.sha512)
                                    H.update(entity_json)
                                    sign = H.hexdigest()

                                    headers = {
                                        "Content-type":
                                        "application/x-www-form-urlencoded",
                                        "Key": UETOPIA_ASSIGNED_GAME_API_KEY,
                                        "Sign": sign
                                    }

                                    conn = httplib.HTTPSConnection(
                                        UETOPIA_API_URL)

                                    conn.request("POST", uri, entity_json,
                                                 headers)
                                    response = conn.getresponse()

                                    #logging.info(response.read())

                                    ## parse the response
                                    jsonstring = str(response.read())
                                    logging.info(jsonstring)
                                    jsonobject = json.loads(jsonstring)

                                    # do something with the response?
                                    if not jsonobject['request_successful']:
                                        logging.info(
                                            'the request was unsuccessful')

                                    logging.info('request was successful')

                        ## empty out the faction's score to prepare for the next season?
                        ## this could result in zombie factions persisting throughout the seasons.
                        ## just going to delete it instead.
                        ## it will get recreated the next time a player signs in

                        factionsController.delete(faction)

                ## set the season to inactive.
                season.active = False
                seasonController.update(season)

                ## also dump firebase values for factions and active_season

                credentials = GoogleCredentials.get_application_default(
                ).create_scoped(_FIREBASE_SCOPES)
                http_auth = credentials.authorize(Http())
                empty_json = json.dumps({})  # just empty
                headers = {"Content-Type": "application/json"}

                URL = "%s/factions.json" % (FIREBASE_DATABASE_ROOT)
                resp, content = http_auth.request(
                    URL,
                    "DELETE",  ## We can delete data with a DELETE request
                    empty_json,
                    headers=headers)

                URL = "%s/active_season.json" % (FIREBASE_DATABASE_ROOT)
                resp, content = http_auth.request(
                    URL,
                    "DELETE",  ## We can delete data with a DELETE request
                    empty_json,
                    headers=headers)

                ## also delete the maps out of the regions
                URL = "%s/regions.json" % (FIREBASE_DATABASE_ROOT)
                resp, content = http_auth.request(
                    URL,
                    "DELETE",  ## We can delete data with a DELETE request
                    empty_json,
                    headers=headers)

            else:
                logging.info('season is not over, starting next round')

                ## clear out user moved bools
                ## there could be a lot of these, so we're going to bactch them like before.
                curs = Cursor()
                more = True

                while more:
                    users_needing_round_reset, curs, more = usersController.list_roundActionUsed_page(
                        start_cursor=curs)

                    for user in users_needing_round_reset:
                        logging.info('processing user')

                        user.roundActionUsed = False
                        usersController.update(user)

                        random_offset = random.randint(
                            2, 10
                        )  ## if you have a lot of volume you can increase this up to 30 or 60
                        taskUrl = '/task/user/firebase/update'
                        taskqueue.add(
                            url=taskUrl,
                            queue_name='firebaseUpdate',
                            params={'key_id': user.key.id()},
                            countdown=random_offset,
                        )

                ## update season
                season.currentRound = season.currentRound + 1
                season.currentRoundCombat = False
                season.currentRoundPositioning = True
                season.currentRoundResults = False

                # save
                seasonController.update(season)

                ## push season out to firebase
                taskUrl = '/task/season/firebase/update'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='firebaseUpdate',
                    params={'key_id': season.key.id()},
                    countdown=2,
                )

                ## push maps out to firebase
                all_maps_for_this_season = mapController.list_by_seasonKeyId(
                    season.key.id())
                for map in all_maps_for_this_season:
                    random_offset = random.randint(2, 10)
                    taskUrl = '/task/map/firebase/update'
                    taskqueue.add(
                        url=taskUrl,
                        queue_name='firebaseUpdate',
                        params={'key_id': map.key.id()},
                        countdown=random_offset,
                    )

                if AUTOMATIC_PHASE_CHANGE:
                    ## requeue the task based on settings in config
                    logging.info('requeueing task')

                    taskUrl = '/task/season/stage_change'
                    taskqueue.add(
                        url=taskUrl,
                        queue_name='seasonStageChange',
                        countdown=ROUND_DURATION_POSITIONING,
                    )
    def post(self):
        """
        Recieve notification when a match is complete.
        Requires http headers:  Key, Sign
        Requires POST parameters:  nonce
        """

        ucontroller = UsersController()
        seasonsController = SeasonsController()
        factionController = FactionsController()
        matchController = MatchController()
        zonesController = ZonesController()

        ## make sure the API key matches first
        incomingApiKey = self.request.headers['Key']
        if incomingApiKey != UETOPIA_ASSIGNED_GAME_API_KEY:
            logging.info('API key mismatch')
            return self.render_json_response(authorization=False,
                                             request_successful=False)

        signature = self.request.headers['Sign']

        logging.info("request.body: %s" % self.request.body)
        logging.info("params: ")
        logging.info(self.request.arguments())
        logging.info("Headers: %s" % self.request.headers)

        sorted_params = self.request.body

        # Hash the params string to produce the Sign header value
        H = hmac.new(UETOPIA_ASSIGNED_GAME_API_SECRET,
                     digestmod=hashlib.sha512)
        H.update(sorted_params)
        sign = H.hexdigest()

        logging.info("sign: %s" % sign)
        logging.info("Hsig: %s" % signature)

        if sign != signature:
            logging.info('signature mismatch')
            return self.render_json_response(authorization=False,
                                             request_successful=False)

        ## At this point, authorization was successful.  Continue with the call.
        logging.info('auth success')

        ## parse the json out of the body.
        jsonstring = self.request.body
        logging.info(jsonstring)
        jsonobject = json.loads(jsonstring)

        ## make sure we have the player, and that it matches one we have already connected
        if 'match_key_id' not in jsonobject:
            logging.info('Did not find match_key_id in json')

            return self.render_json_response(authorization=True,
                                             request_successful=False)

        match = matchController.get_by_key_id(jsonobject['match_key_id'])
        if not match:
            logging.info('match was not found.')
            return self.render_json_response(authorization=True,
                                             request_successful=False)

        ## we need the active season too
        active_season = seasonsController.get_active()
        if not active_season:
            logging.info('active_season was not found.')
            return self.render_json_response(authorization=True,
                                             request_successful=False)

        ## grab information about the winner - this is a gameplayerkeyid
        if 'winning_user_key_id' in jsonobject:
            logging.info('Found winning_user_key_id in json')

            winning_user = ucontroller.get_by_uetopia_playerKeyId(
                jsonobject['winning_user_key_id'])
            if not winning_user:
                logging.info('winning user not found')
                return self.render_json_response(authorization=True,
                                                 request_successful=False)

            ## make sure we have this group/faction in the database already.
            winning_faction = factionController.get_by_key_id(
                winning_user.currentFactionKeyId)
            if not winning_faction:
                logging.info('could not find the connected winning_faction')
                return self.render_json_response(authorization=True,
                                                 request_successful=False)

        # get the zone associated with this match
        zone = zonesController.get_by_key_id(match.zoneKeyId)
        if not zone:
            logging.info('could not find the connected zone')
            return self.render_json_response(authorization=True,
                                             request_successful=False)

        ## was the winner the attacker or defender?
        if winning_user.key.id() == zone.userCaptainKeyId:
            logging.info('defender was the winner')

            ## get both users and set active to false.
            previous_defender = ucontroller.get_by_key_id(
                match.defenderUserKeyId)

            previous_defender.metaGameActive = False
            ucontroller.update(previous_defender)

            ## the attacker is not going to get picked up at the season round change step, so do it now.
            taskUrl = '/task/user/firebase/update'
            taskqueue.add(
                url=taskUrl,
                queue_name='firebaseUpdate',
                params={'key_id': previous_defender.key.id()},
                countdown=2,
            )

            previous_attacker = ucontroller.get_by_key_id(
                match.attackerUserKeyId)

            previous_attacker.metaGameActive = False
            ucontroller.update(previous_attacker)

            ## the attacker is not going to get picked up at the season round change step, so do it now.
            taskUrl = '/task/user/firebase/update'
            taskqueue.add(
                url=taskUrl,
                queue_name='firebaseUpdate',
                params={'key_id': previous_attacker.key.id()},
                countdown=2,
            )

        else:
            logging.info('attacker was the winner')

            ## change around the keys in the captain's user records.
            previous_controller_user = ucontroller.get_by_key_id(
                zone.userCaptainKeyId)
            if previous_controller_user:
                logging.info('found previous user record  - cleaning it out')
                previous_controller_user.holdingZoneKeyId = None
                previous_controller_user.holdingZone = False
                previous_controller_user.holdingZoneTitle = None
                ## also set active to false.  We need them to reenable meta mode in-game.
                previous_controller_user.metaGameActive = False
                ucontroller.update(previous_controller_user)

                ## the defender is not going to get picked up at the season round change step, so do it now.
                taskUrl = '/task/user/firebase/update'
                taskqueue.add(
                    url=taskUrl,
                    queue_name='firebaseUpdate',
                    params={'key_id': previous_controller_user.key.id()},
                    countdown=2,
                )

            winning_user.holdingZoneKeyId = zone.key.id()
            winning_user.holdingZone = True
            winning_user.holdingZoneTitle = zone.title
            ## also set active to false.  We need them to reenable meta mode in-game.
            winning_user.metaGameActive = False
            ucontroller.update(winning_user)

            ## firebase? - just wait until the round is over and do them all

        ## in either case, just store the winning results in the match record so that we can process it when the round ends.
        match.winningUserKeyId = winning_user.key.id()
        match.winningUserTitle = winning_user.title
        match.winningTeamTitle = winning_user.currentTeamTitle
        match.winningFactionKeyId = winning_user.currentFactionKeyId
        match.winningFactionTitle = winning_user.currentFactionTag
        match.winningUetopiaGamePlayerKeyId = winning_user.uetopia_playerKeyId

        match.active = True
        match.verified = True
        match.expired = False

        # save match
        matchController.update(match)

        return self.render_json_response(authorization=True,
                                         request_successful=True)
Exemple #11
0
    def clientSignIn(self, request):
        """ Connect and verify a user's login token - This is called when a user signs in. """
        logging.info('clientSignIn')

        # Verify Firebase auth.
        #logging.info(self.request_state)
        try:
            id_token = self.request_state.headers['x-metagame-auth'].split(
                ' ').pop()
        except:
            logging.error('Missing JWT')
            return ClientConnectResponse(
                response_message='Error: Authentication Token Missing.',
                response_successful=False)

        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            logging.error('Firebase Unauth')
            response = ClientConnectResponse(
                user_id=None,
                refresh_token=True,
                response_message='Firebase Unauth.',
                response_successful=False)
            return response
        else:
            logging.info('claims verified')

            try:
                name = claims['name']
            except:
                name = claims['email']

            ## get this user or create if needed
            uController = UsersController()

            authorized_user = uController.get_by_firebaseUser(
                claims['user_id'])
            if not authorized_user:
                logging.info('no user record found')

                logging.info('creating new user')

                authorized_user = uController.create(
                    firebaseUser=claims['user_id'],
                    title=name,
                    uetopia_connected=False,
                    admin=False,
                    metaGameActive=False,
                    roundActionUsed=False,
                    currentFactionKeyId=None,
                    currentFactionTag=None,
                    currentFactionLead=False,
                    currentFactionTeamLead=False,
                    currentTeamKeyId=None,
                    currentTeamCaptain=False,
                    holdingZoneKeyId=None,
                    holdingZone=False,
                    holdingZoneTitle=None)

                # push a chat out to discord
                http_auth = Http()
                headers = {"Content-Type": "application/json"}
                URL = ADMIN_DISCORD_WEBHOOK
                message = "%s | %s " % (name, claims['email'])
                discord_data = {
                    "embeds": [{
                        "title": "New User",
                        "url": "https://example.com",
                        "description": message
                    }]
                }
                data = json.dumps(discord_data)
                resp, content = http_auth.request(URL,
                                                  "POST",
                                                  data,
                                                  headers=headers)

            else:
                logging.info('user found')

            #taskUrl='/task/user/firebase/update'
            #taskqueue.add(url=taskUrl, queue_name='firebaseUpdate', params={'key_id': authorized_user.key.id()}, countdown = 2,)

        response = ClientConnectResponse(
            user_id=claims['user_id'],
            uetopia_connected=authorized_user.uetopia_connected,
            response_message='Connected successfully.',
            response_successful=True)

        return response
Exemple #12
0
    def uetopiaValidate(self, request):
        """ Validate a user's uetopia security code and connect thier account."""
        logging.info('uetopiaValidate')

        # Verify Firebase auth.
        #logging.info(self.request_state)
        try:
            id_token = self.request_state.headers['x-metagame-auth'].split(
                ' ').pop()
        except:
            logging.error('Missing JWT')
            return ClientConnectResponse(
                response_message='Error: Authentication Token Missing.',
                response_successful=False)

        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            logging.error('Firebase Unauth')
            response = ClientConnectResponse(
                user_id=None,
                refresh_token=True,
                response_message='Firebase Unauth.',
                response_successful=False)
            return response

        logging.info('claims verified')

        try:
            name = claims['name']
        except:
            name = claims['email']

        ## get this user
        uController = UsersController()
        factionController = FactionsController()
        seasonController = SeasonsController()

        authorized_user = uController.get_by_firebaseUser(claims['user_id'])
        if not authorized_user:
            logging.warning(
                'no user record found - this can happen on first sign in')

            response = ClientConnectResponse(
                user_id=claims['user_id'],
                uetopia_connected=False,
                response_message='No user record found',
                response_successful=False)
            ## Users do not get created in this call ever.  It causes occasional duplicates because of the way firebase spams refreshes on the login screen.
            return response

        logging.info('user found')

        #Set up an API request to the uetopia backend to check this security code
        # we'll be sending the gameKeyId, and the user's security code
        # this security code will be erased regardless of the results of this request, so if it failed, the user must start over with a new code.

        uri = "/api/v1/game/metagame/verify"

        params = OrderedDict([("nonce", time.time()), ("encryption", "sha512"),
                              ("securityCode", request.security_code)])

        params = urllib.urlencode(params)

        # Hash the params string to produce the Sign header value
        H = hmac.new(UETOPIA_ASSIGNED_GAME_API_SECRET,
                     digestmod=hashlib.sha512)
        H.update(params)
        sign = H.hexdigest()

        headers = {
            "Content-type": "application/x-www-form-urlencoded",
            "Key": UETOPIA_ASSIGNED_GAME_API_KEY,
            "Sign": sign
        }

        conn = httplib.HTTPSConnection(UETOPIA_API_URL)

        conn.request("POST", uri, params, headers)
        response = conn.getresponse()

        #logging.info(response.read())

        ## parse the response
        jsonstring = str(response.read())
        logging.info(jsonstring)
        jsonobject = json.loads(jsonstring)

        # do something with the response
        if not jsonobject['request_successful']:
            logging.info('the validation request was unsuccessful')

            response = ClientConnectResponse(
                user_id=claims['user_id'],
                uetopia_connected=False,
                response_message='Verification failed.  %s' %
                jsonobject['error'],
                response_successful=False)

            return response

        logging.info('validation was successful')

        authorized_user.uetopia_connected = True
        authorized_user.uetopia_playerKeyId = jsonobject['player_key_id']

        active_season_key = None
        active_season = seasonController.get_active()
        if active_season:
            logging.info('Active season found')
            active_season_key = active_season.key.id()

        ## grab information about the group and team
        if 'group_key_id' in jsonobject:
            logging.info('Found group_key_id in json')

            ## make sure we have this group/faction in the database already.
            faction = factionController.get_by_uetopia_groupKeyId(
                jsonobject['group_key_id'])
            if faction:
                logging.info('found an existing faction')

                ## check to see if the faction is in the active semester
                if not faction.activeSeasonKeyId:
                    logging.info(
                        'this faction has not been active in the current semester yet.  Setting defaults'
                    )

                    faction.activeSeasonKeyId = active_season_key
                    faction.energy = FACTION_STARTING_ENERGY
                    faction.materials = FACTION_STARTING_MATERIALS
                    faction.control = FACTION_STARTING_CONTROL

                    factionController.update(faction)

                if faction.activeSeasonKeyId != active_season.key.id():
                    ## this should hopefully not happen, keeping it here just in case
                    logging.error(
                        'this faction has the wrong season applied.  This should not happen.  Make sure this gets cleared out on season change.'
                    )

                    faction.activeSeasonKeyId = active_season_key
                    faction.energy = FACTION_STARTING_ENERGY
                    faction.materials = FACTION_STARTING_MATERIALS
                    faction.control = FACTION_STARTING_CONTROL

                    factionController.update(faction)

            else:
                logging.info('faction not found - adding it')

                faction = factionController.create(
                    tag=jsonobject['group_tag'],
                    #title = ndb.StringProperty(indexed=False)
                    #description = ndb.TextProperty(indexed=False)
                    uetopia_groupKeyId=jsonobject['group_key_id'],
                    activeSeasonKeyId=active_season_key,
                    energy=FACTION_STARTING_ENERGY,
                    materials=FACTION_STARTING_MATERIALS,
                    control=FACTION_STARTING_CONTROL)

            ## with a faction, make sure the user has this faction selected, and there were no changes to the users permissions

            authorized_user.currentFactionKeyId = faction.key.id()
            authorized_user.currentFactionTag = jsonobject['group_tag']
            try:
                authorized_user.currentFactionLead = jsonobject[
                    'metagame_faction_lead']
            except:
                authorized_user.currentFactionLead = False

            try:
                authorized_user.currentFactionTeamLead = jsonobject[
                    'metagame_team_lead']
            except:
                authorized_user.currentFactionTeamLead = False

        uController.update(authorized_user)

        ## check for team
        if jsonobject['team_key_id']:
            logging.info('found a team')

            ## we want to be able to send back the team captain status so that the JS client can prompt the user to take appropriate actions

        taskUrl = '/task/user/firebase/update'
        taskqueue.add(
            url=taskUrl,
            queue_name='firebaseUpdate',
            params={'key_id': authorized_user.key.id()},
            countdown=2,
        )

        response = ClientConnectResponse(
            response_message='Connected successfully.',
            response_successful=True)

        return response
Exemple #13
0
    def clientConnect(self, request):
        """ Connect and verify a user's login token - This is called when a user loads the website and is already logged in. also sometimes after signing in."""
        logging.info('clientConnect')

        #user = endpoints.get_current_user()
        #logging.info(user)

        # Verify Firebase auth.
        #logging.info(self.request_state)
        try:
            id_token = self.request_state.headers['x-metagame-auth'].split(
                ' ').pop()
        except:
            logging.error('Missing JWT')
            return ClientConnectResponse(
                response_message='Error: Authentication Token Missing.',
                response_successful=False)

        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            logging.error('Firebase Unauth')
            response = ClientConnectResponse(
                user_id=None,
                refresh_token=True,
                response_message='Firebase Unauth.',
                response_successful=False)
            return response
        else:
            logging.info('claims verified')

            try:
                name = claims['name']
            except:
                name = claims['email']

            ## get this user
            uController = UsersController()

            authorized_user = uController.get_by_firebaseUser(
                claims['user_id'])
            if not authorized_user:
                logging.warning(
                    'no user record found - this can happen on first sign in')

                response = ClientConnectResponse(
                    user_id=claims['user_id'],
                    uetopia_connected=False,
                    response_message='No user record found',
                    response_successful=False)
                ## Users do not get created in this call ever.  It causes occasional duplicates because of the way firebase spams refreshes on the login screen.
                return response
            else:
                logging.info('user found')

        taskUrl = '/task/user/firebase/update'
        taskqueue.add(
            url=taskUrl,
            queue_name='firebaseUpdate',
            params={'key_id': authorized_user.key.id()},
            countdown=2,
        )

        response = ClientConnectResponse(
            user_id=claims['user_id'],
            uetopia_connected=authorized_user.uetopia_connected,
            refresh_token=False,
            response_message='Connected successfully.',
            response_successful=True)

        return response
Exemple #14
0
    def fill(self, request):
        # Verify Firebase auth.
        #claims = firebase_helper.verify_auth_token(self.request_state)
        id_token = self.request_state.headers['x-metagame-auth'].split(
            ' ').pop()
        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            ## TODO make this more modular, somehow.  We have no idea who this user is at this point, so can't write to the firebase user record.
            logging.error('Firebase Unauth')
            response = ZoneResponse(response_message='Firebase Unauth.',
                                    response_successful=False)
            return response

        authorized_user = UsersController().get_by_firebaseUser(
            claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return ZoneResponse(
                response_message='Error: No User Record Found. ',
                response_successful=False)

        if not authorized_user.admin:
            logging.info('no admin record found')
            return ZoneResponse(
                response_message='Error: No Admin Record Found. ',
                response_successful=False)

        ## Look up the map
        mapController = MapsController()
        zoneController = ZonesController()

        map = mapController.get_by_key_id(request.mapKeyId)
        if not map:
            logging.info('map not found by key')
            return ZoneResponse(response_message='Error: No map Found. ',
                                response_successful=False)

        ## keep track of the results so we can push the whole json struct to firebase all at once.
        map_json = {}

        vertical_rows = []

        # loop over the horizontal
        for verticalIndex in range(map.zoneCountVertical):

            logging.info('filling verticalIndex: %s' % verticalIndex)
            horizontal_row = []

            for horizontalIndex in range(map.zoneCountHorizontal):

                logging.info('filling horizontalIndex')

                ## Roll to see which zone should fill here (defined in configuration.py)
                zoneToUse = random.randint(1, 100)
                logging.info('random roll: %s' % zoneToUse)

                ## loop over the zonetypes
                for zone_type in ZONE_TYPES:
                    if zone_type['probability'] >= zoneToUse:
                        logging.info('found zone')

                        ## roll for energy, materials, control based on the zone type
                        rand_energy = random.randint(zone_type['energyMin'],
                                                     zone_type['energyMax'])
                        rand_materials = random.randint(
                            zone_type['materialsMin'],
                            zone_type['materialsMax'])
                        rand_control = random.randint(zone_type['controlMin'],
                                                      zone_type['controlMax'])

                        zone = zoneController.create(
                            engine_travel_url=zone_type['engine_travel_url'],
                            title=zone_type['title'],
                            mapKeyId=map.key.id(),
                            mapTitle=map.title,
                            seasonKeyId=map.seasonKeyId,
                            seasonTitle=map.seasonTitle,
                            seasonActive=map.seasonActive,
                            regionKeyId=map.regionKeyId,
                            regionTitle=map.regionTitle,
                            regionDatacenterLocation=map.
                            regionDatacenterLocation,
                            horizontalIndex=horizontalIndex,
                            verticalIndex=verticalIndex,
                            energy=rand_energy,
                            materials=rand_materials,
                            control=rand_control,
                            validZone=zone_type['validZone'])

                        horizontal_row.append(zone.to_json())

                        break

            vertical_rows.append(horizontal_row)

        #credentials = AppAssertionCredentials('https://www.googleapis.com/auth/sqlservice.admin')
        credentials = GoogleCredentials.get_application_default(
        ).create_scoped(_FIREBASE_SCOPES)

        http_auth = credentials.authorize(Http())

        map.zones = vertical_rows
        map_json = map.to_json()

        model_json = json.dumps(map_json)

        #logging.info(model_json)
        headers = {"Content-Type": "application/json"}

        URL = "%s/regions/%s/maps/%s.json" % (FIREBASE_DATABASE_ROOT,
                                              map.regionKeyId, map.key.id())
        logging.info(URL)
        resp, content = http_auth.request(
            URL,
            "PUT",  ## Write or replace data to a defined path,
            model_json,
            headers=headers)

        #logging.info(resp)
        #logging.info(content)

        return ZoneResponse(response_message="Map Filled",
                            response_successful=True)
Exemple #15
0
    def zoneBid(self, request):
        """ Bid to attack a zone """
        logging.info("zoneBid")

        # Verify Firebase auth.
        #logging.info(self.request_state)
        try:
            id_token = self.request_state.headers['x-metagame-auth'].split(
                ' ').pop()
        except:
            logging.error('Missing JWT')
            return BidResponse(
                response_message='Error: Authentication Token Missing.',
                response_successful=False)

        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
        if not claims:
            logging.error('Firebase Unauth')
            return BidResponse(
                response_message='Error: Firebase Authentication Missing.',
                response_successful=False)

        userController = UsersController()

        authorized_user = userController.get_by_firebaseUser(claims['user_id'])

        if not authorized_user:
            logging.info('no user record found')
            return BidResponse(
                response_message='Error: No User Record Found. ',
                response_successful=False)

        if not authorized_user.currentFactionTeamLead:
            logging.info(
                'User does not have currentFactionTeamLead permission')
            return BidResponse(
                response_message=
                'Error: You do not have the Team Lead permission. ',
                response_successful=False)

        if authorized_user.roundActionUsed:
            logging.info('User has already taken an action this round')
            return BidResponse(
                response_message=
                'Error: You have already taken an action this round. ',
                response_successful=False)

        zoneController = ZonesController()
        bidController = BidsController()
        seasonController = SeasonsController()
        factionsController = FactionsController()

        ## check season - make sure positioning is set to true.
        season = seasonController.get_active()
        if not season:
            logging.info('No Active season found')
            return BidResponse(
                response_message='Error: The active season was not found. ',
                response_successful=False)

        if not season.currentRoundPositioning:
            logging.info('Positioning is not currently enabled - cannot bid')
            return BidResponse(
                response_message=
                'Error: Positioning round is not active.  Cannot bid.',
                response_successful=False)

        zone = zoneController.get_by_key_id(request.zoneKeyId)
        if not zone:
            logging.info('the zone was not found')
            return BidResponse(
                response_message='Error: The zone was not found. ',
                response_successful=False)

        ## check min/max
        if request.bidAmount < MINIMUM_BID:
            logging.info('bid below minimum')
            return BidResponse(response_message='Error: The bid was too low. ',
                               response_successful=False)

        if request.bidAmount > MAXIMUM_BID:
            logging.info('bid above maximum')
            return BidResponse(
                response_message='Error: The bid was too high. ',
                response_successful=False)

        ## make sure the faction can afford it

        faction = factionsController.get_by_key_id(
            authorized_user.currentFactionKeyId)
        if not faction:
            logging.info('the faction was not found')
            return BidResponse(
                response_message='Error: The faction was not found. ',
                response_successful=False)

        if faction.energy < request.bidAmount:
            logging.info('the faction cannot afford this bid')
            return BidResponse(
                response_message='Error: The faction cannot afford this bid. ',
                response_successful=False)

        ## Check to see if this team was previously defending.  If they were, we need to remove them from the defending zone immediately.
        defending_zone = zoneController.get_controlled_by_userCaptainKeyId(
            authorized_user.key.id())
        if defending_zone:
            logging.info('found a zone that this user/team is defending')
            if defending_zone.key.id() == zone.key.id():
                logging.info(
                    'it is the same zone.  This should not happen.  Ignoring')
                return BidResponse(
                    response_message=
                    'Error: Cannot bid on a zone that is currently being defended.',
                    response_successful=False)
            else:
                logging.info(
                    'This is a different zone.  Moving the team out of the defended zone.'
                )
                defending_zone.controlled = False
                defending_zone.factionKeyId = None
                defending_zone.factionTag = None
                defending_zone.userCaptainKeyId = None
                defending_zone.userCaptainTitle = None
                defending_zone.teamTitle = None

                #save
                zoneController.update(defending_zone)

                ## firebase update?  Can just leave it for the next push I think....

        ## Remove the amount from the faction
        ## TODO - use a more fault tolerant approach for serious projects.
        ## for now just subtracting
        faction.energy = faction.energy - request.bidAmount
        # and since we're about to update the faction anyway, make sure it has the current season key
        faction.activeSeasonKeyId = season.key.id()
        factionsController.update(faction)

        ## record the bid
        bidController.create(
            zoneKeyId=zone.key.id(),
            zoneTitle=zone.title,
            mapKeyId=zone.mapKeyId,
            mapTitle=zone.mapTitle,
            seasonKeyId=season.key.id(),
            seasonTitle=season.title,
            seasonActive=season.active,
            regionKeyId=zone.regionKeyId,
            regionTitle=zone.regionTitle,

            # connections to the user, party and faction
            #teamKeyId = ndb.IntegerProperty(indexed=False)
            #teamTitle = ndb.StringProperty(indexed=False)
            factionKeyId=faction.key.id(),
            factionTitle=faction.tag,
            factionTag=faction.tag,
            userKeyId=authorized_user.key.id(),
            userTitle=authorized_user.title,
            uetopiaGamePlayerKeyId=authorized_user.uetopia_playerKeyId,
            roundIndex=season.currentRound,
            bidAmount=request.bidAmount,
            highBid=False,
            bidProcessed=False,
            bidReturned=False,
        )

        ## update the player - make the bid buttons and "waiting for move" dissapear

        authorized_user.roundActionUsed = True
        userController.update(authorized_user)

        taskUrl = '/task/user/firebase/update'
        taskqueue.add(
            url=taskUrl,
            queue_name='firebaseUpdate',
            params={'key_id': authorized_user.key.id()},
            countdown=2,
        )

        response = BidResponse(response_message="Bid placed.",
                               response_successful=True)

        return response
    def post(self):
        """
        Recieve Notification when a player starts meta game mode
        Requires http headers:  Key, Sign
        Requires POST parameters:  nonce, securityCode
        """

        ucontroller = UsersController()
        seasonsController = SeasonsController()
        factionController = FactionsController()

        ## make sure the API key matches first
        incomingApiKey = self.request.headers['Key']
        if incomingApiKey != UETOPIA_ASSIGNED_GAME_API_KEY:
            logging.info('API key mismatch')
            return self.render_json_response(authorization=False,
                                             request_successful=False)

        signature = self.request.headers['Sign']

        logging.info("request.body: %s" % self.request.body)
        logging.info("params: ")
        logging.info(self.request.arguments())
        logging.info("Headers: %s" % self.request.headers)

        sorted_params = self.request.body

        # Hash the params string to produce the Sign header value
        H = hmac.new(UETOPIA_ASSIGNED_GAME_API_SECRET,
                     digestmod=hashlib.sha512)
        H.update(sorted_params)
        sign = H.hexdigest()

        logging.info("sign: %s" % sign)
        logging.info("Hsig: %s" % signature)

        if sign != signature:
            logging.info('signature mismatch')
            return self.render_json_response(authorization=False,
                                             request_successful=False)

        ## At this point, authorization was successful.  Continue with the call.
        logging.info('auth success')

        ## parse the json out of the body.
        jsonstring = self.request.body
        logging.info(jsonstring)
        jsonobject = json.loads(jsonstring)

        ## make sure we have the player, and that it matches one we have already connected
        if 'player_key_id' not in jsonobject:
            logging.info('Did not find player_key_id in json')

            return self.render_json_response(authorization=True,
                                             request_successful=False)

        user = ucontroller.get_by_uetopia_playerKeyId(
            jsonobject['player_key_id'])
        if not user:
            logging.info(
                'user was not found.  make sure they connect to metagame first.'
            )
            return self.render_json_response(authorization=True,
                                             request_successful=False)

        ## we need the active season too
        active_season = seasonsController.get_active()
        if not active_season:
            logging.info('active_season was not found.')
            return self.render_json_response(authorization=True,
                                             request_successful=False)

        ## grab information about the group and team
        if 'group_key_id' in jsonobject:
            logging.info('Found group_key_id in json')

            ## make sure we have this group/faction in the database already.
            faction = factionController.get_by_uetopia_groupKeyId(
                jsonobject['group_key_id'])
            if faction:
                logging.info('found an existing faction')

                ## check to see if the faction is in the active semester
                if not faction.activeSeasonKeyId:
                    logging.info(
                        'this faction has not been active in the current semester yet.  Setting defaults'
                    )

                    faction.activeSeasonKeyId = active_season.key.id()
                    faction.energy = FACTION_STARTING_ENERGY
                    faction.materials = FACTION_STARTING_MATERIALS
                    faction.control = FACTION_STARTING_CONTROL

                    factionController.update(faction)

                if faction.activeSeasonKeyId != active_season.key.id():
                    ## this should hopefully not happen, keeping it here just in case
                    logging.error(
                        'this faction has the wrong season applied.  This should not happen.  Make sure this gets cleared out on season change.'
                    )

                    faction.activeSeasonKeyId = active_season.key.id()
                    faction.energy = FACTION_STARTING_ENERGY
                    faction.materials = FACTION_STARTING_MATERIALS
                    faction.control = FACTION_STARTING_CONTROL

                    factionController.update(faction)

            else:
                logging.info('faction not found - adding it')

                faction = factionController.create(
                    tag=jsonobject['group_tag'],
                    #title = ndb.StringProperty(indexed=False)
                    #description = ndb.TextProperty(indexed=False)
                    uetopia_groupKeyId=jsonobject['group_key_id'],
                    activeSeasonKeyId=active_season.key.id(),
                    energy=FACTION_STARTING_ENERGY,
                    materials=FACTION_STARTING_MATERIALS,
                    control=FACTION_STARTING_CONTROL)

            ## with a faction, make sure the user has this faction selected, and there were no changes to the users permissions

            user.currentFactionKeyId = faction.key.id()
            user.currentFactionTag = jsonobject['group_tag']
            user.currentFactionLead = jsonobject['metagame_faction_lead']
            user.currentFactionTeamLead = jsonobject['metagame_team_lead']

        if 'team_key_id' in jsonobject:
            logging.info('Found team_key_id in json')

            user.currentTeamKeyId = jsonobject['team_key_id']
            user.currentTeamCaptain = jsonobject['team_captain']

        ## update the user record.
        user.metaGameActive = True
        ucontroller.update(user)

        ## push out to firebase
        taskUrl = '/task/user/firebase/update'
        taskqueue.add(
            url=taskUrl,
            queue_name='firebaseUpdate',
            params={'key_id': user.key.id()},
            countdown=2,
        )

        ## return status success so that uetopia knows the call worked.

        ## TODO - anything else we need to send back to the uetopia backend at this stage?
        ## custom json probably...

        return self.render_json_response(authorization=True,
                                         request_successful=True)