def favourite_create(self, data, sesh): """Favourite (Create) Adds a favourite to the logged in thrower 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])) # If someone tries to add themselves if data['id'] == sesh['thrower']['_id']: return Services.Effect(False) # Make sure the thrower exists if not Thrower.exists(data['id']): return Services.Effect(error=(1104, data['id'])) # Add the thrower to the logged in thrower's favourites and return the # result return Services.Effect( Favourites.add(sesh['thrower']['_id'], data['id']))
def favourites_read(self, data, sesh): """Favourites Returns all favourites for the logged in thrower Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ # Fetch the favourites for the thrower lFavourites = Favourites.get(sesh['thrower']['_id'], raw=['ids']) # If there's none if not lFavourites: return Services.Effect([]) # Look up all the throwers using the IDs lThrowers = Thrower.get(lFavourites['ids'], raw=['_id', 'alias']) # Return what's found return Services.Effect(lThrowers)
def pull_read(self, data, sesh): """Pull A client is requesting an update on anything they might be looking at 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If we have messages to delete if 'messages' in data and data['messages']: Sync.clear(sesh.id(), data['service'], data['key'], data['messages']) # Get as many messages as possible lRet = Sync.pull(sesh.id(), data['service'], data['key']) # Return whatever was found return Services.Effect(lRet)
def clear_update(self, data, sesh): """Clear Clears the given number of messages from the sync cache 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, ['service', 'key', 'count']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Clear the messages from the sync cache Sync.clear(sesh.id(), data['service'], data['key'], data['count']) # Return OK return Services.Effect(True)
def join_create(self, data, sesh): """Join Connects a session to an account or contact so that any messages associated with either are stored for later polling 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Update the sync cache Sync.join(sesh.id(), data['service'], data['key']) # Return OK return Services.Effect(True)
def practiceData_read(self, data, sesh): """Practice Data Returns all the data points associated with a practice session 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])) # Fetch the practice data dPractice = Practice.get(data['id'], raw=['data', 'stats']) if not dPractice: return Services.Effect(error=(1104, 'practice:%s' % data['id'])) # Return the data return Services.Effect(dPractice)
def leave_create(self, data, sesh): """Leave Disconnects a session from an account or contact so that messages are no longer collected for it 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Update the sync cache Sync.leave(sesh.id(), data['service'], data['key']) # Return OK return Services.Effect(True)
def matchRequest_create(self, data, sesh): """Match Request (Create) Creates a new match request and notifies the opponent 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, ['opponent', 'org']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find opponent dOpponent = Thrower.get(data['opponent'], raw=['alias']) if not dOpponent: return Services.Effect(error=(1104, 'thrower:%s' % data['opponent'])) # Create a new request try: oRequest = MatchRequest({ "_created": int(time()), "initiator": sesh['thrower']['_id'], "opponent": data['opponent'], "org": data['org'] }) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oRequest.create(): return Services.Effect(error=1100) # Sync the data for anyone listening Sync.push( 'auth', 'requests-%s' % data['opponent'], { "type": 'match_request', "_id": oRequest['_id'], "initiator": sesh['thrower']['_id'], "alias": sesh['thrower']['alias'], "org": data['org'] }) # Return the ID of the new request return Services.Effect(oRequest['_id'])
def practicePattern_update(self, data, sesh): """Practice Pattern (Update) Replaces an existing Practice Pattern for the current thrower 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 pattern oPattern = PracticePattern.get(data['_id']) if not oPattern: return Services.Effect(error=(1104, 'practice_pattern:%s' % data['_id'])) # If the user has no rights if oPattern['thrower'] != sesh['thrower']['_id']: return Services.Effect(error=1000) # Remove fields that can't be changed del data['_id'] if '_created' in data: del data['_created'] if 'thrower' in data: del data['thrower'] # Update whatever is left, catch any invalid values lErrors = [] for k in data: try: oPattern[k] = data[k] except ValueError as e: lErrors.extend(e.args[0]) # If there's any errors if lErrors: return Services.Effect(error=(103, lErrors)) # Update the pattern oPattern.save() # Return OK return Services.Effect(True)
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)
def matchRequest_delete(self, data, sesh): """Match Request (Delete) Refuses a match request and deletes it 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 deleter is not the initiator or opponent if sesh['thrower']['_id'] != oRequest['initiator'] and \ sesh['thrower']['_id'] != oRequest['opponent']: return Services.Effect(error=1000) # Delete it if not oRequest.delete(): return Services.Effect(error=1102) # If the initiator retracted their request if sesh['thrower']['_id'] == oRequest['initiator']: # Let the opponent know Sync.push('auth', 'requests-%s' % oRequest['opponent'], { "type": "match_request_delete", "id": data['id'] }) # Else the opponent rejected the request else: # Let the initiator know Sync.push('auth', 'request-%s' % data['id'], {"type": "rejected"}) # Return OK return Services.Effect(True)
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'])
def passwdForgot_update(self, data): """Password Forgot (Change Password) Validates the key and changes the password to the given value Arguments: data {dict} -- Data sent with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['passwd', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Look for the thrower by the key oThrower = Thrower.get(filter={"forgot": { "key": data['key'] }}, limit=1) if not oThrower: return Services.Effect( error=1203) # Don't let people know if the key exists or not # Check if we even have a forgot section, or the key has expired, or the # key is invalid if 'forgot' not in oThrower or \ oThrower['forgot']['expires'] <= int(time()) or \ oThrower['forgot']['key'] != data['key']: return Services.Effect(error=1203) # Make sure the new password is strong enough if not Thrower.passwordStrength(data['passwd']): return Services.Effect(error=1204) # Store the new password and update oThrower['passwd'] = Thrower.passwordHash(data['passwd']) oThrower.fieldDelete('forgot') oThrower.save(changes=False) # Return OK return Services.Effect(True)
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)
def signin_create(self, data): """Signin Signs a user into 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])) # Look for the thrower by alias oThrower = Thrower.get(data['alias'], index='alias', limit=1) if not oThrower: return Services.Effect(error=1201) # Validate the password if not oThrower.passwordValidate(data['passwd']): return Services.Effect(error=1201) # Create a new session oSesh = Sesh.create() # Store the thrower ID and information in it oSesh['thrower'] = oThrower.record() # Save the session oSesh.save() # Return the session ID and primary thrower data return Services.Effect({ "session": oSesh.id(), "thrower": { "_id": oSesh['thrower']['_id'], "alias": oSesh['thrower']['alias'], "org": oSesh['thrower']['org'] } })
def match_delete(self, data, sesh): """Match (Delete) Deletes an existing match, can only be done if it's not finished 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])) # Get the match dMatch = Match.get(data['id'], raw=['finished', 'initiator', 'opponent']) if not dMatch: return Services.Effect(error=(1104, 'watl_match:%s' % data['id'])) # If the thrower is neither the initiator or opponent, or the match is # already marked finished if (dMatch['initiator'] != sesh['thrower']['_id'] and \ dMatch['opponent'] != sesh['thrower']['_id']) or \ dMatch['finished']: return Services.Effect(error=1000) # Else, attempt to delete the record Match.deleteGet(data['id']) # Notify anyone watching the match Sync.push('watl', 'match-%s' % data['id'], {"type": "deleted"}) # Return OK return Services.Effect(True)
def matchRequest_read(self, data, sesh): """Match Request (Read) Fetchs a match request and returns it 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 dRequest = MatchRequest.get(data['id'], raw=True) if not dRequest: return Services.Effect(error=(1104, 'match_request:%s' % data['id'])) # Get the ID of the other thrower if sesh['thrower']['_id'] == dRequest['initiator']: sID = dRequest['opponent'] elif sesh['thrower']['_id'] == dRequest['opponent']: sID = dRequest['initiator'] else: return Services.Effect(error=1000) # Get the other thrower's alias and add it to the request dAlias = Thrower.get(sID, raw=['alias']) dRequest['alias'] = dAlias and dAlias['alias'] or 'N/A' # Return the request return Services.Effect(dRequest)
def throwerOrg_update(self, data, sesh): """Thrower Org Changes the default organisation 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, ['org']) 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) # Set the new org try: oThrower['org'] = data['org'] except ValueError: return Services.Effect(error=(1000, [('org', 'invalid')])) # Save oThrower.save(changes={"creator": sesh['thrower']['_id']}) # Update the session sesh['thrower']['org'] = data['org'] sesh.save() # Return OK return Services.Effect(True)
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)
def throwerAlias_update(self, data, sesh): """Thrower Alias Changes the alias associated with the thrower 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, ['alias']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If the alias is invalid if not Thrower.struct()['tree']['alias'].valid(data['alias']): return Services.Effect(error=(1001, [('alias', 'invalid')])) # 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'])) # Try to change the alias if not Thrower.alias(sesh['thrower']['_id'], data['alias']): return Services.Effect(False) # Update the session sesh['thrower']['alias'] = data['alias'] sesh.save() # Return OK return Services.Effect(True)
def search_read(self, data, sesh): """Search Looks up throwers by alias 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, ['q']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Run a search and return the results return Services.Effect(Thrower.search(data['q']))
def throwerPasswd_update(self, data, sesh): """Thrower Password Changes the password 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, ['passwd', 'new_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['passwd']): return Services.Effect(error=(1001, [('passwd', 'invalid')])) # Make sure the new password is strong enough if not Thrower.passwordStrength(data['new_passwd']): return Services.Effect(error=1204) # Set the new password and save oThrower['passwd'] = Thrower.passwordHash(data['new_passwd']) oThrower.save(changes={"creator": sesh['thrower']['_id']}) # Return OK return Services.Effect(True)
def practicePattern_create(self, data, sesh): """Practice Pattern (Create) Creates a new Practice Pattern for the current thrower 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, ['title', 'descr', 'throws']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Create the instance try: oPattern = PracticePattern({ "_created": int(time()), "thrower": sesh['thrower']['_id'], "title": data['title'], "descr": data['descr'], "throws": data['throws'] }) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oPattern.create(): return Services.Effect(error=1100) # Return the new ID return Services.Effect(oPattern['_id'])
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']) })
def practicePattern_delete(self, data, sesh): """Practice Pattern (Delete) Deletes an existing Practice Pattern for the current thrower 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 pattern oPattern = PracticePattern.get(data['id']) if not oPattern: return Services.Effect(error=(1104, 'practice_pattern:%s' % data['id'])) # If the user has no rights if oPattern['thrower'] != sesh['thrower']['_id']: return Services.Effect(error=1000) # Delete the pattern if not oPattern.delete(): return Services.Effect(False) # Return OK return Services.Effect(True)
def favourite_delete(self, data, sesh): """Favourite (Delete) Removes a favourite from the logged in thrower 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])) # Remove the thrower from the logged in thrower's favourites and return # the result return Services.Effect( Favourites.remove(sesh['thrower']['_id'], data['id']))
def matchRequests_read(self, data, sesh): """Match Requests Returns all open match requests regardless of initiator or opponent Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ # Init the return dRet = {} # Find all the requests the thrower initiated dRet['initiator'] = MatchRequest.get(sesh['thrower']['_id'], index='initiator', raw=['_id', 'opponent', 'org']) # Find all the requests in which the thrower is the opponent dRet['opponent'] = MatchRequest.get(sesh['thrower']['_id'], index='opponent', raw=['_id', 'initiator', 'org']) # Get all the thrower IDs lThrowers = [] for d in dRet['initiator']: lThrowers.append(d['opponent']) for d in dRet['opponent']: lThrowers.append(d['initiator']) # Get all the thrower aliases dAliases = lThrowers and \ {d['_id']:d['alias'] for d in Thrower.get(list(set(lThrowers)), raw=['_id', 'alias'])} or \ {} # Add the alias to each record for d in dRet['initiator']: d['alias'] = d['opponent'] in dAliases and dAliases[ d['opponent']] or 'N/A' for d in dRet['opponent']: d['alias'] = d['initiator'] in dAliases and dAliases[ d['initiator']] or 'N/A' # Return all the records return Services.Effect(dRet)
def session_read(self, data, sesh): """Session Returns the ID of the thrower logged into the current session Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ return Services.Effect({ "_id": sesh['thrower']['_id'], "alias": sesh['thrower']['alias'], "org": sesh['thrower']['org'] })
def signout_create(self, data, sesh): """Signout Called to sign out a user and destroy their session Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the user Returns: Services.Effect """ # Close the session so it can no longer be found/used sesh.close() # Return OK return Services.Effect(True)
def practicePatterns_read(self, data, sesh): """Practice Patterns Fetches the list of patterns beloning to the logged in thrower Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Fetch all patterns for the current thrower and return them return Services.Effect( PracticePattern.get(sesh['thrower']['_id'], index='thrower', raw=True, orderby='title'))