Beispiel #1
0
def emailEffect(effect, info):
	"""Email Effect

	Sends the effect to a developer so they are aware of the error

	Arguments:
		effect {Services.Effect} -- The effect to send
		info {dict} -- Info about the request

	Returns:
		None
	"""

	# Try to send an e-mail
	oEffect = Services.create('communications', 'email', {
		"_internal_": Services.internalKey(),
		"from": "noreply@%s" % Conf.get(("domain", "primary")),
		"subject": "external error",
		"text_body": "Info: %s\nEffect: %s" % (str(info), str(effect)),
		"to": Conf.get(("email", "errors"))
	})

	# If there's an error
	if oEffect.errorExists():
		raise oEffect
Beispiel #2
0
    def matchRequest_update(self, data, sesh):
        """Match Request (Update)

		Accepts a match request and creates the match with the proper service,
		then notifies both throwers of the ID of the new match

		Arguments:
			data {dict} -- Data sent with the request
			sesh {Sesh._Session} -- The session associated with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['id'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Find the request
        oRequest = MatchRequest.get(data['id'])
        if not oRequest:
            return Services.Effect(error=(1104,
                                          'match_request:%s' % data['id']))

        # If the accepter is not the opponent
        if sesh['thrower']['_id'] != oRequest['opponent']:
            return Services.Effect(error=1000)

        # Create a new match in the proper service
        oEffect = Services.create(
            oRequest['org'].lower(), 'match', {
                "_internal_": Services.internalKey(),
                "initiator": oRequest['initiator'],
                "opponent": oRequest['opponent']
            }, sesh)
        if oEffect.errorExists():
            return oEffect

        # Delete the request
        oRequest.delete()

        # Notify the initiator of the new match
        Sync.push('auth', 'request-%s' % data['id'], {
            "type": "accepted",
            "match": oEffect.data
        })

        # Return the ID of the new match
        return Services.Effect(oEffect.data)
Beispiel #3
0
    def match_create(self, data, sesh):
        """Match (Create)

		Creates a new match and returns its ID

		Arguments:
			data {dict} -- Data sent with the request
			sesh {Sesh._Session} -- Session associated with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['_internal_', 'initiator', 'opponent'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Verify the key, remove it if it's ok
        if not Services.internalKey(data['_internal_']):
            return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY)
        del data['_internal_']

        # Create a new match instance
        try:
            oMatch = Match({
                "_created": int(time()),
                "finished": False,
                "calculated": False,
                "initiator": data['initiator'],
                "opponent": data['opponent'],
                "game_finished": {
                    "i": False,
                    "o": False
                },
                "game": {
                    "i": {},
                    "o": {}
                }
            })
        except ValueError as e:
            return Services.Effect(error=(1001, e.args[0]))

        # Store the instance
        if not oMatch.create():
            return Services.Effect(error=1100)

        # Return the ID
        return Services.Effect(oMatch['_id'])
Beispiel #4
0
    def matchUnfinished_read(self, data, sesh):
        """Match Unfinished

		Returns any unfinished matches the thrower is involved in

		Arguments:
			data {dict} -- Data sent with the request
			sesh {Sesh._Session} -- Session associated with the request

		Returns:
			Services.Effect
		"""

        # Find all unfinished matches the thrower is involved in
        lMatches = Match.unfinished(sesh['thrower']['_id'])

        # If there's none
        if not lMatches:
            return Services.Effect([])

        # Get the other throwers
        lThrowers = []
        for d in lMatches:
            lThrowers.append(
                d['initiator'] == sesh['thrower']['_id'] and d['opponent']
                or d['initiator'])

        # If there's any throwers
        dAliases = {}
        if lThrowers:
            oEffect = Services.read('auth', 'thrower/aliases', {
                "_internal_": Services.internalKey(),
                "ids": list(set(lThrowers))
            })
            if oEffect.errorExists():
                return oEffect
            dAliases = oEffect.data

        # Add the aliases to each record
        for d in lMatches:
            s = d['initiator'] == sesh['thrower']['_id'] and d[
                'opponent'] or d['initiator']
            d['alias'] = s in dAliases and dAliases[s] or 'N/A'

        # Return the matches
        return Services.Effect(lMatches)
Beispiel #5
0
    def throwerVerify_update(self, data):
        """Thrower Verify

		Sets the thrower's email to verified if the key is valid

		Arguments:
			data {dict} -- Data sent with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['_internal_', 'id', 'verify'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Verify the key, remove it if it's ok
        if not Services.internalKey(data['_internal_']):
            return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY)
        del data['_internal_']

        # Find the thrower
        oThrower = Thrower.get(data['id'])

        # If it doesn't exist
        if not oThrower:
            return Services.Effect(error=(1104, data['id']))

        # If the thrower is already verified
        if oThrower['verified'] == True:
            return Services.Effect(True)

        # If the code is not valid
        if data['verify'] != oThrower['verified']:
            return Services.Effect(error=1205)

        # Update the thrower
        oThrower['verified'] = True
        oThrower.save(changes=False)

        # Return OK
        return Services.Effect(True)
Beispiel #6
0
def verify(id, key):

	# Contact the auth service to verify the key
	oEffect = Services.update('auth', 'thrower/verify', {
		"_internal_": Services.internalKey(),
		"id": id,
		"verify": key
	})

	# If there's an error
	if oEffect.errorExists():
		print(oEffect)
		emailEffect(oEffect, {"request":"verify", "id": id, "key":key})
		return show500()

	# Redirect to main site
	dConf = Conf.get("domain")
	bottle.redirect("%s://%s/#verified" % (
		dConf['protocol'],
		dConf['primary']
	))
Beispiel #7
0
    def match_read(self, data, sesh):
        """Match (Read)

		Fetches and returns the stats from an existing match

		Arguments:
			data {dict} -- Data sent with the request
			sesh {Sesh._Session} -- Session associated with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['id'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Find the match
        dMatch = Match.get(data['id'], raw=True)
        if not dMatch:
            return Services.Effect(error=(1104, 'watl_match:%s' % data['id']))

        # Get the aliases of both throwers
        oEffect = Services.read(
            'auth', 'thrower/aliases', {
                "_internal_": Services.internalKey(),
                "ids": [dMatch['opponent'], dMatch['initiator']]
            })
        if oEffect.errorExists():
            return oEffect

        # Add the aliases
        dMatch['initiator_alias'] = oEffect.data[dMatch['initiator']]
        dMatch['opponent_alias'] = oEffect.data[dMatch['opponent']]

        # Else return the match
        return Services.Effect(dMatch)
Beispiel #8
0
    def throwerAliases_read(self, data):
        """Thrower Aliases

		Recieves a list of thrower IDs and returns a dictionary of IDs to
		aliases

		Arguments:
			data {dict} -- Data sent with the request

		Returns:
			Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['_internal_', 'ids'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Verify the key, remove it if it's ok
        if not Services.internalKey(data['_internal_']):
            return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY)
        del data['_internal_']

        # If the IDs are not a list
        if not isinstance(data['ids'], list):
            return Services.Effect(error=(1001, [('ids', 'not a list')]))

        # If the list is empty
        if not data['ids']:
            return Services.Effect({})

        # Get and return all the thrower aliases
        return Services.Effect({
            d['_id']: d['alias']
            for d in Thrower.get(data['ids'], raw=['_id', 'alias'])
        })
Beispiel #9
0
    def email(self, data):
        """Email

		Sends an e-mail, by either sending it to the queue, or sending it
		directly

		Arguments:
			data {dict} -- The data sent with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['_internal_', 'subject', 'to'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, 'missing')
                                                 for f in e.args]))

        # Verify the key, remove it if it's ok
        if not Services.internalKey(data['_internal_']):
            return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY)
        del data['_internal_']

        # Check that we have at least one type of body
        if 'html_body' not in data and 'text_body' not in data:
            return Services.Effect(error=1300)

        # Add None if either body is missing
        if 'html_body' not in data: data['html_body'] = None
        if 'text_body' not in data: data['text_body'] = None

        # If the from is not set
        if 'from' not in data:
            data['from'] = self.fromDefault

        # If we got a _queue_ value
        if '_queue_' in data:

            # Store it
            sQueueKey = data.pop('_queue_')

            # If it's not valid
            if not _queueKey(data, sQueueKey):
                return Services.Effect(error=1001)

            # Else, we're good
            data['_queue_'] = True

        # If we are sending direct, or we got a valid request from the queue
        if self.emailMethod == 'direct' or '_queue_' in data:

            # Init the attachments var
            mAttachments = None

            # If there's an attachment
            if 'attachments' in data:

                # Make sure it's a list
                if not isinstance(data['attachments'], (list, tuple)):
                    data['attachments'] = [data['attachments']]

                # Loop through the attachments
                for i in range(len(data['attachments'])):

                    # If we didn't get a dictionary
                    if not isinstance(data['attachments'][i], dict):
                        return Services.Effect(error=(1301,
                                                      "attachments.%d" % i))

                    # If the fields are missing
                    try:
                        DictHelper.eval(data['attachments'][i],
                                        ['body', 'filename'])
                    except ValueError as e:
                        return Services.Effects(error=(1001,
                                                       [("attachments.%d.%s" %
                                                         (i, s), 'invalid')
                                                        for s in e.args]))

                    # Try to decode the base64
                    try:
                        data['attachments'][i]['body'] = b64decode(
                            data['attachments'][i]['body'])
                    except TypeError:
                        return Services.Effect(error=1302)

                # Set the attachments from the data
                mAttachments = data['attachments']

            # Send the e-mail
            iRes = SMTP.send(data['to'],
                             data['subject'],
                             text_body=data['text_body'],
                             html_body=data['html_body'],
                             from_=data['from'],
                             attachments=mAttachments)

            # If there was an error
            if iRes != SMTP.OK:
                return Services.Effect(error=(1303, '%i %s' %
                                              (iRes, SMTP.lastError())))

        # Else, we are sending to the queue first
        else:

            # Add a queue key to the data
            data['_queue_'] = self._queueKey(data)

            # Send the data to the queue service
            oEff = Services.create(
                'queue', 'msg', {
                    "_internal_": Services.internalKey(),
                    "service": "communications",
                    "path": "email",
                    "method": "create",
                    "data": data
                })

            # Return if there's an error
            if oEff.errorExists():
                return oEff

        # Return OK
        return Services.Effect(True)
Beispiel #10
0
    def throwerEmail_update(self, data, sesh):
        """Thrower Email

		Changes the email for the current signed in user

		Arguments:
			data {dict} -- Data sent with the request
			sesh {Sesh._Session} -- The session associated with the user

		Returns:
			Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['email', 'email_passwd'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Find the thrower
        oThrower = Thrower.get(sesh['thrower']['_id'])
        if not oThrower:
            return Services.Effect(error=1104)

        # Validate the password
        if not oThrower.passwordValidate(data['email_passwd']):
            return Services.Effect(error=(1001, [('email_passwd', 'invalid')]))

        # Make sure the email is valid structurally
        if not _emailRegex.match(data['email']):
            return Services.Effect(error=(1001, [('email', 'invalid')]))

        # Look for someone else with that email
        dThrower = Thrower.get(data['email'], index='email', raw=['_id'])
        if dThrower:
            return Services.Effect(error=(1206, data['email']))

        # Update the email and verified fields
        try:
            oThrower['email'] = data['email']
            oThrower['verified'] = StrHelper.random(32, '_0x')
        except ValueError as e:
            return Services.Effect(error=(1001, e.args[0]))

        # Update the thrower
        oThrower.save(changes={"creator": sesh['thrower']['_id']})

        # Send en e-mail for verification
        dConf = Conf.get("domain")
        sURL = "%s://external.%s/verify/%s/%s" % (
            dConf['protocol'], dConf['primary'], oThrower['_id'],
            oThrower['verified'])
        oEffect = Services.create(
            'communications', 'email', {
                "_internal_":
                Services.internalKey(),
                "html_body":
                Templates.generate('email/verify.html', {"url": sURL},
                                   oThrower['locale']),
                "subject":
                Templates.generate('email/verify_subject.txt', {},
                                   oThrower['locale']),
                "to":
                data['email'],
            })
        if oEffect.errorExists():
            return oEffect

        # Return OK
        return Services.Effect(True)
Beispiel #11
0
    def signup_create(self, data):
        """Signup

		Creates a new user on the system

		Arguments:
			data {dict} -- The data passed to the request

		Returns:
			Result
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['alias', 'passwd'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Make sure the email is valid structurally
        if 'email' in data and not _emailRegex.match(data['email']):
            return Services.Effect(error=(1001, [('email', 'invalid')]))

        # Make sure the password is strong enough
        if not Thrower.passwordStrength(data['passwd']):
            return Services.Effect(error=1204)

        # Look for someone else with that alias
        dThrower = Thrower.get(data['alias'], index='alias', raw=['_id'])
        if dThrower:
            return Services.Effect(error=(1200, data['alias']))

        # If an e-mail was passed
        if 'email' in data:

            # Look for someone else with that email
            dThrower = Thrower.get(data['email'], index='email', raw=['_id'])
            if dThrower:
                return Services.Effect(error=(1206, data['email']))

        # If no language was passed
        if 'locale' not in data:
            data['locale'] = 'en-US'

        # Init the thrower data
        dThrower = {
            "_created": int(time()),
            "alias": data['alias'],
            "locale": data['locale'],
            "org": 'org' in data and data['org'] or 'natf',
            "passwd": Thrower.passwordHash(data['passwd']),
            "verified": StrHelper.random(32, '_0x')
        }

        # If there's an email
        if 'email' in data:
            dThrower['email'] = data['email']
            dThrower['verified'] = StrHelper.random(32, '_0x')
        else:
            dThrower['verified'] = False

        # Create an instance
        try:
            oThrower = Thrower(dThrower)
        except ValueError as e:
            return Services.Effect(error=(1001, e.args[0]))

        # Store the instance
        if not oThrower.create(changes={"creator": "signup"}):
            return Services.Effect(error=1100)

        Services.create(
            'communications', 'email', {
                "_internal_":
                Services.internalKey(),
                "text_body":
                "Alias: %s\nEmail: %s" %
                (data['alias'], ('email' in data and data['email'] or '')),
                "subject":
                "Axegains Signup",
                "to":
                "*****@*****.**",
            })

        # If there's an e-mail
        if 'email' in data:

            # Send en e-mail for verification
            dConf = Conf.get("domain")
            sURL = "%s://external.%s/verify/%s/%s" % (
                dConf['protocol'], dConf['primary'], oThrower['_id'],
                oThrower['verified'])
            oEffect = Services.create(
                'communications', 'email', {
                    "_internal_":
                    Services.internalKey(),
                    "html_body":
                    Templates.generate('email/verify.html', {"url": sURL},
                                       data['locale']),
                    "subject":
                    Templates.generate('email/verify_subject.txt', {},
                                       data['locale']),
                    "to":
                    data['email'],
                })
            if oEffect.errorExists():
                return oEffect

        # If we don't already have a session, create one
        if 'session' not in data:
            oSesh = Sesh.create()

        # Else, load the existing session
        else:
            oSesh = Sesh.start(data['session'])

        # Add the thrower ID to it
        oSesh['thrower'] = oThrower.record()
        oSesh.save()

        # Return the session token
        return Services.Effect({
            "session": oSesh.id(),
            "thrower": {
                "_id": oSesh['thrower']['_id'],
                "alias": oSesh['thrower']['alias'],
                "org": oSesh['thrower']['org']
            }
        })
Beispiel #12
0
    def passwdForgot_create(self, data):
        """Password Forgot (Generate)

		Creates the key that will be used to allow a user to change their
		password if they forgot it

		Arguments:
			data {dict} -- Data sent with the request

		Returns:
			Services.Effect
		"""

        # Verify fields
        try:
            DictHelper.eval(data, ['email'])
        except ValueError as e:
            return Services.Effect(error=(1001, [(f, "missing")
                                                 for f in e.args]))

        # Look for the thrower by email
        oThrower = Thrower.get(data['email'], index='email', limit=1)
        if not oThrower:
            return Services.Effect(True)

        # Is there already a key in the thrower?
        if 'forgot' in oThrower and 'regenerate' not in data:

            # Is it not expired?
            if oThrower['forgot']['expires'] > int(time()):
                return Services.Effect(True)

        # Update the thrower with a timestamp (for expiry) and the key
        sKey = StrHelper.random(32, '_0x')
        oThrower['forgot'] = {"expires": int(time()) + 300, "key": sKey}
        if not oThrower.save(changes=False):
            return Services.Effect(error=1103)

        # Get the domain config
        dConf = Conf.get("domain")

        # Forgot email template variables
        dTpl = {
            "key":
            sKey,
            "url":
            "%s://%s/#forgot=%s" % (dConf['protocol'], dConf['primary'], sKey)
        }

        # Email the user the key
        oEffect = Services.create(
            'communications', 'email', {
                "_internal_":
                Services.internalKey(),
                "html_body":
                Templates.generate('email/forgot.html', dTpl,
                                   oThrower['locale']),
                "subject":
                Templates.generate('email/forgot_subject.txt', {},
                                   oThrower['locale']),
                "to":
                data['email'],
            })
        if oEffect.errorExists():
            return oEffect

        # Return OK
        return Services.Effect(True)