Example #1
0
	def login(self,env,start_response):
		
		cl = vanilla.getContentLength(env)
		if cl == None:
			return vanilla.http_error(411,env,start_response,'missing Content-Length header')
		
		content = env['wsgi.input'].read(cl)
		query = urlparse.parse_qs(content)
		
		if 'username' not in query:
			return vanilla.http_error(400,env,start_response,msg='missing username')
		#Use first occurence from query string
		username = query['username'][0]
		
		if 'password' not in query:
			return vanilla.http_error(400,env,start_response,msg='missing password')
		#Use first occurence from query string
		password = query['password'][0]
		
		userId = self.authenticateUser(username,password)
		if userId == None:
			self.logger.info('Failed authorization for user:%s' , username)
			return vanilla.sendJsonWsgiResponse(env,start_response,{'error':'bad username or password'})
		
		session = self.sm.startSession(username,userId)
			
		return vanilla.sendJsonWsgiResponse(env,start_response,self.getResponseForSession(session),additionalHeaders=[session.getCookie()])
Example #2
0
    def __call__(self, env, start_response):
        #Extract and normalize the path
        #Posix path may not be the best approach here but
        #no alternate has been found
        pathInfo = posixpath.normpath(env['PATH_INFO'])

        #Split the path into components. Drop the first
        #since it should always be the empty string
        pathComponents = pathInfo.split('/')[1 + self.pathDepth:]

        env['fairywren.pathComponents'] = pathComponents

        requestMethod = env['REQUEST_METHOD']

        #The default is request not found
        errorCode = 404

        #Find a resource with a patch matching the requested one
        for resource in self.resources:
            kwargs = resource.wants(pathComponents)

            if kwargs == None:
                continue

            #If the method does not agree with the resource, the
            #code is method not supported
            if requestMethod != resource.method:
                errorCode = 405
                continue

            self.logger.debug('%s:%s handled by %s', requestMethod, pathInfo,
                              resource.getName())
            if resource.requireAuthentication:
                session = self.sm.getSession(env)

                if session == None:
                    return vanilla.sendJsonWsgiResponse(
                        env, start_response, restInterface.NOT_AUTHENTICATED)

                #Check to see if the resource requires authorization
                if resource.requireAuthorization:
                    authorized = resource.allowSelf and resource.getOwnerId(
                        *pathComponents) == session.getId()
                    authorized |= self.authorizeUser(session,
                                                     resource.allowedRoles)
                    if not authorized:
                        self.logger.debug('%s:%s not authorized for %s',
                                          requestMethod, pathInfo,
                                          session.getUsername())
                        return vanilla.sendJsonWsgiResponse(
                            env, start_response, restInterface.NOT_AUTHORIZED)

                return resource(env, start_response, session, **kwargs)
            else:
                return resource(env, start_response, **kwargs)

        self.logger.info('%s:%s not handled, %d', requestMethod, pathInfo,
                         errorCode)
        return vanilla.http_error(errorCode, env, start_response)
Example #3
0
	def __call__(self,env,start_response):		
		#Extract and normalize the path
		#Posix path may not be the best approach here but 
		#no alternate has been found
		pathInfo = posixpath.normpath(env['PATH_INFO'])
		
		#Split the path into components. Drop the first
		#since it should always be the empty string
		pathComponents = pathInfo.split('/')[1+self.pathDepth:]
		
		env['fairywren.pathComponents'] = pathComponents
		
		requestMethod = env['REQUEST_METHOD']
		
		#The default is request not found
		errorCode = 404
		
		#Find a resource with a patch matching the requested one
		for resource in self.resources:	
			kwargs = resource.wants(pathComponents)

			if kwargs == None:
				continue

			#If the method does not agree with the resource, the
			#code is method not supported
			if requestMethod != resource.method:
				errorCode = 405	
				continue							
			
			self.logger.debug('%s:%s handled by %s',requestMethod,pathInfo,resource.getName())
			if resource.requireAuthentication:
				session = self.sm.getSession(env)

				if session == None:
					return vanilla.sendJsonWsgiResponse(env,start_response,restInterface.NOT_AUTHENTICATED)
				
				#Check to see if the resource requires authorization
				if resource.requireAuthorization:
					authorized = resource.allowSelf and resource.getOwnerId(*pathComponents)==session.getId()
					authorized |= self.authorizeUser(session,resource.allowedRoles)
					if not authorized:
						self.logger.debug('%s:%s not authorized for %s',requestMethod,pathInfo,session.getUsername())
						return vanilla.sendJsonWsgiResponse(env,start_response,restInterface.NOT_AUTHORIZED)

				return resource(env,start_response,session,**kwargs)
			else:
				return resource(env,start_response,**kwargs)
				
		self.logger.info('%s:%s not handled, %d', requestMethod,pathInfo,errorCode)
		return vanilla.http_error(errorCode,env,start_response)
Example #4
0
	def listInvites(self,env,start_response,session,uid):
		uid = int(uid,16)
		#Potential pitfall in this implementation:
		#If a user is authorized to perform a GET on this resource but
		#user for the uid does not exist, this stil returns an empty list
		response = { 'invites' : list(self.users.listInvitesByUser(uid)) }
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #5
0
	def changeRolesOfUser(self,env,start_response,session,uid,roles):
		uid = int(uid,16)
		try:
			self.users.setUserRoles(roles,uid)
		except ValueError as e:
			return vanilla.http_error(400,env,start_response,msg=e.message)
		return vanilla.sendJsonWsgiResponse(env,start_response,{'roles':self.users.getUserRoles(uid)})
Example #6
0
	def changePassword(self,env,start_response,session,uid,password):
		uid = int(uid,16)
		
		if None == self.authmgr.changePassword(uid,password):
			return vanilla.http_error(400,env,start_response)
		
		return vanilla.sendJsonWsgiResponse(env,start_response,{})
Example #7
0
	def inviteStatus(self,env,start_response,secret):
		secret = base64.urlsafe_b64decode(secret + '=')
		try:
			claimed =self.users.getInviteState(secret)
		except ValueError as e:
			return vanilla.http_error(404,env,start_response,msg=e.message)
		
		return vanilla.sendJsonWsgiResponse(env,start_response,{'claimed':claimed})
Example #8
0
    def showSession(self, env, start_response, session):
        response = self.getResponseForSession(session)

        return vanilla.sendJsonWsgiResponse(
            env,
            start_response,
            response,
            additionalHeaders=[session.getCookie()])
Example #9
0
	def getSwarm(self,env,start_response,session):
		response = self.swarm.getPeers()
		
		for peer in response.itervalues():
			for d in peer:
				d.pop('peerId')
				
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #10
0
	def addUser(self,env,start_response,session,password,username):
		
		try:
			resourceForNewUser,_ = self.users.addUser(username,password)
		except users.UserAlreadyExists:		
			return vanilla.http_error(409,env,start_response,'user already exists')
		
		response = { 'href' : resourceForNewUser } 
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #11
0
	def updateTorrent(self,env,start_response,session,uid,extended,title):
		uid = int(uid,16)
		
		try:
			self.torrents.updateTorrent(uid,title,extended)
		except ValueError as e:
			return vanilla.http_error(404,env,start_response,msg=e.message)			
			
		return vanilla.sendJsonWsgiResponse(env,start_response,{})
Example #12
0
	def deleteTorrent(self,env,start_response,session,uid):
		uid = int(uid,16)
		
		try:
			torrent = self.torrents.deleteTorrent(uid)
		except ValueError as e:
			return vanilla.http_error(404,env,start_response,msg=e.message)
			
		return vanilla.sendJsonWsgiResponse(env,start_response,{})
Example #13
0
	def claimInvite(self,env,start_response,secret,username,password):
		secret = base64.urlsafe_b64decode(secret + '=')
		
		try:
			newuser = self.users.claimInvite(secret,username,password)
		except users.UserAlreadyExists:
			return vanilla.http_error(409,env,start_response,msg='User with that name already exists')
		except ValueError as e:
			return vanilla.http_error(404,env,start_response,msg=e.message)
		
		return vanilla.sendJsonWsgiResponse(env,start_response,{'href' : newuser})
Example #14
0
	def userInfo(self,env,start_response,session,uid):
		uid = int(uid,16)
		
		response = self.users.getInfo(uid)
		
		if response == None:
			return vanilla.http_error(404,env,start_response)
			
		if session.getId() == uid:
			response['announce'] = { 'href': self.torrents.getAnnounceUrlForUser(uid) }
				
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #15
0
	def torrentInfo(self,env,start_response,session,uid):
		uid = int(uid,16)
		response = self.torrents.getInfo(uid)
		if response == None:
			return vanilla.http_error(404,env,start_response,msg='no such torrent')

		torrentInfoHash = response.pop('infoHash')
		numSeeds,numLeeches = self.peers.getNumberOfPeers(torrentInfoHash)
		response['extended'] = self.torrents.getExtendedInfo(uid)
		response['seeds'] = numSeeds
		response['leeches'] = numLeeches
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #16
0
    def login(self, env, start_response):

        cl = vanilla.getContentLength(env)
        if cl == None:
            return vanilla.http_error(411, env, start_response,
                                      'missing Content-Length header')

        content = env['wsgi.input'].read(cl)
        query = urlparse.parse_qs(content)

        if 'username' not in query:
            return vanilla.http_error(400,
                                      env,
                                      start_response,
                                      msg='missing username')
        #Use first occurence from query string
        username = query['username'][0]

        if 'password' not in query:
            return vanilla.http_error(400,
                                      env,
                                      start_response,
                                      msg='missing password')
        #Use first occurence from query string
        password = query['password'][0]

        userId = self.authenticateUser(username, password)
        if userId == None:
            self.logger.info('Failed authorization for user:%s', username)
            return vanilla.sendJsonWsgiResponse(
                env, start_response, {'error': 'bad username or password'})

        session = self.sm.startSession(username, userId)

        return vanilla.sendJsonWsgiResponse(
            env,
            start_response,
            self.getResponseForSession(session),
            additionalHeaders=[session.getCookie()])
Example #17
0
	def searchTorrents(self,env,start_response,session,query):
		tokens = query.get('token')
		if tokens == None:
			return vanilla.http_error(400,env,start_response,'search must have at least one instance of token parameter')
			
		if len(tokens) > 5:
			return vanilla.http_error(400,env,start_response,'search may not have more than 5 tokens')
			
		listOfTorrents = []
		for torrent in self.torrents.searchTorrents(tokens):
			torrentInfoHash = torrent.pop('infoHash')
			torrent.pop('id')
			seeds, leeches = self.peers.getNumberOfPeers(torrentInfoHash)
			torrent['seeds'] = seeds
			torrent['leeches'] = leeches
			listOfTorrents.append(torrent)
			
		return vanilla.sendJsonWsgiResponse(env,start_response,
		{'torrents': listOfTorrents})
Example #18
0
	def createTorrent(self,env,start_response,session):
		
		if not 'CONTENT_TYPE' in env:
			return vanilla.http_error(411,env,start_response,'missing Content-Type header')
		
		contentType = env['CONTENT_TYPE']
			
		if 'multipart/form-data' not in contentType:
			return vanilla.http_error(415,env,start_response,'must be form upload')
		
		forms,files = multipart.parse_form_data(env)
		
		if 'torrent' not in files or 'title' not in forms:
			return vanilla.http_error(400,env,start_response,'missing torrent or title')
		
		try:
			extended = json.loads(forms.get('extended','{}'))
		except ValueError:
			return vanilla.http_error(400,env,start_response,'bad extended info')
			
		if not isinstance(extended,dict):
			return vanilla.http_error(400,env,start_response,'extended info must be dict')
		
		data = files['torrent'].raw
		try:
			newTorrent = torrents.Torrent.fromBencodedData(data)
		except ValueError as e:
			return vanilla.http_error(400,env,start_response,str(e))
		
		response = {}
		response['redownload'] = newTorrent.scrub()
		response['redownload'] |= self.torrents.getAnnounceUrlForUser(session.getId())!=newTorrent.getAnnounceUrl()
		
		try:	
			url,infoUrl = self.torrents.addTorrent(newTorrent,forms['title'],session.getId(),extended)
		except ValueError as e: #Thrown when a torrent already exists with this info hash
			return vanilla.http_error(400,env,start_response,e.message)
			
		response['metainfo'] = { 'href' : url }
		response['info'] = { 'href' : infoUrl }
			
		return vanilla.sendJsonWsgiResponse(env,start_response,response)
Example #19
0
	def listTorrents(self,env,start_response,session):
		
		if 'QUERY_STRING' not in env:
			query = {}
		else:
			query = urlparse.parse_qs(env['QUERY_STRING'])
			
		if 'search' in query:
			return self.searchTorrents(env,start_response,session,query)
		
		#Use the first occurence of the supplied parameter
		#With a default 
		resultSize = query.get('resultSize',[self.MAX_TORRENTS_PER_RESULT])[0]
		
		try:
			resultSize = int(resultSize)
		except ValueError:
			return vanilla.http_error(400,env,start_response,'resultSize must be integer')
		
		#Use the first occurence of the supplied parameter
		#With a default of zero	
		subset = query.get('subset',[0])[0]
		
		try:
			subset = int(subset)
		except ValueError:
			return vanilla.http_error(400,env,start_response,'subset must be integer')

		listOfTorrents = []
		
		for torrent in self.torrents.getTorrents(resultSize,subset):
			torrent.pop('id')
			torrentInfoHash = torrent.pop('infoHash')
			seeds, leeches = self.peers.getNumberOfPeers(torrentInfoHash)
			torrent['seeds'] = seeds
			torrent['leeches'] = leeches
			listOfTorrents.append(torrent)

		return vanilla.sendJsonWsgiResponse(env,start_response,
		{'torrents' : listOfTorrents ,'numSubsets' : int(math.ceil(self.torrents.getNumTorrents() / float(resultSize)))} )
Example #20
0
	def showSession(self,env,start_response,session):		
		response = self.getResponseForSession(session)
	
		return vanilla.sendJsonWsgiResponse(env,start_response,response,additionalHeaders=[session.getCookie()])	
Example #21
0
	def listRoles(self,env,start_response,session):
		return vanilla.sendJsonWsgiResponse(env,start_response,{'roles':self.getRoles()})
Example #22
0
	def listRolesOfUser(self,env,start_response,session,uid):
		uid = int(uid,16)
		#Potential pitfall in this implementation:
		#If the user for the uid does not exist, this stil returns an empty list
		return vanilla.sendJsonWsgiResponse(env,start_response,{'roles':self.users.getUserRoles(uid)})
Example #23
0
	def createInvite(self,env,start_response,session):
		pathOfNewInvite = self.users.createInvite(session.getId())
		return vanilla.sendJsonWsgiResponse(env,start_response,{'href':pathOfNewInvite})