import http.cookies import threading from hydrus.core import HydrusConstants as HC from hydrus.core import HydrusData from hydrus.core import HydrusExceptions from hydrus.core import HydrusGlobals as HG from hydrus.core import HydrusPaths from hydrus.core import HydrusSerialisable from hydrus.core.networking import HydrusNetwork from hydrus.core.networking import HydrusNetworkVariableHandling from hydrus.core.networking import HydrusNetworking from hydrus.core.networking import HydrusServerRequest from hydrus.core.networking import HydrusServerResources from hydrus.server import ServerFiles class HydrusResourceBusyCheck( HydrusServerResources.Resource ): def __init__( self ): HydrusServerResources.Resource.__init__( self ) self._server_version_string = HC.service_string_lookup[ HC.SERVER_ADMIN ] + '/' + str( HC.NETWORK_VERSION ) def render_GET( self, request: HydrusServerRequest.HydrusRequest ): request.setResponseCode( 200 ) request.setHeader( 'Server', self._server_version_string ) if HG.server_busy.locked(): return b'1' else: return b'0' class HydrusResourceHydrusNetwork( HydrusServerResources.HydrusResource ): BLOCKED_WHEN_BUSY = True def _callbackParseGETArgs( self, request: HydrusServerRequest.HydrusRequest ): parsed_request_args = HydrusNetworkVariableHandling.ParseHydrusNetworkGETArgs( request.args ) request.parsed_request_args = parsed_request_args return request def _callbackParsePOSTArgs( self, request: HydrusServerRequest.HydrusRequest ): request.content.seek( 0 ) if not request.requestHeaders.hasHeader( 'Content-Type' ): parsed_request_args = HydrusNetworkVariableHandling.ParsedRequestArguments() else: content_types = request.requestHeaders.getRawHeaders( 'Content-Type' ) content_type = content_types[0] try: mime = HC.mime_enum_lookup[ content_type ] except: raise HydrusExceptions.BadRequestException( 'Did not recognise Content-Type header!' ) total_bytes_read = 0 if mime == HC.APPLICATION_JSON: json_string = request.content.read() total_bytes_read += len( json_string ) parsed_request_args = HydrusNetworkVariableHandling.ParseNetworkBytesToParsedHydrusArgs( json_string ) else: ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() request.temp_file_info = ( os_file_handle, temp_path ) with open( temp_path, 'wb' ) as f: for block in HydrusPaths.ReadFileLikeAsBlocks( request.content ): f.write( block ) total_bytes_read += len( block ) decompression_bombs_ok = self._DecompressionBombsOK( request ) parsed_request_args = HydrusNetworkVariableHandling.ParseFileArguments( temp_path, decompression_bombs_ok ) self._reportDataUsed( request, total_bytes_read ) request.parsed_request_args = parsed_request_args return request def _checkService( self, request: HydrusServerRequest.HydrusRequest ): if self.BLOCKED_WHEN_BUSY and HG.server_busy.locked(): raise HydrusExceptions.ServerBusyException( 'This server is busy, please try again later.' ) return request class HydrusResourceAccessKey( HydrusResourceHydrusNetwork ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): registration_key = request.parsed_request_args[ 'registration_key' ] access_key = HG.server_controller.Read( 'access_key', self._service_key, registration_key ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'access_key' : access_key } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceAccessKeyVerification( HydrusResourceHydrusNetwork ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): access_key = self._parseHydrusNetworkAccessKey( request ) verified = HG.server_controller.Read( 'verify_access_key', self._service_key, access_key ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'verified' : verified } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceAutoCreateAccountTypes( HydrusResourceHydrusNetwork ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): account_types = HG.server_controller.Read( 'auto_create_account_types', self._service_key ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'account_types' : account_types } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedAutoCreateRegistrationKey( HydrusResourceHydrusNetwork ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): account_type_key = request.parsed_request_args[ 'account_type_key' ] registration_key = HG.server_controller.Read( 'auto_create_registration_key', self._service_key, account_type_key ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'registration_key' : registration_key } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceShutdown( HydrusResourceHydrusNetwork ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): HG.server_controller.ShutdownFromServer() response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceSessionKey( HydrusResourceHydrusNetwork ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): access_key = self._parseHydrusNetworkAccessKey( request ) ( session_key, expires ) = HG.server_controller.server_session_manager.AddSession( self._service_key, access_key ) now = HydrusData.GetNow() max_age = expires - now cookies = [ ( 'session_key', session_key.hex(), { 'max_age' : str( max_age ), 'path' : '/' } ) ] response_context = HydrusServerResources.ResponseContext( 200, cookies = cookies ) return response_context class HydrusResourceRestricted( HydrusResourceHydrusNetwork ): def _callbackCheckAccountRestrictions( self, request: HydrusServerRequest.HydrusRequest ): HydrusResourceHydrusNetwork._callbackCheckAccountRestrictions( self, request ) self._checkAccount( request ) self._checkAccountPermissions( request ) return request def _callbackEstablishAccountFromHeader( self, request: HydrusServerRequest.HydrusRequest ): session_key = None if request.requestHeaders.hasHeader( 'Cookie' ): cookie_texts = request.requestHeaders.getRawHeaders( 'Cookie' ) cookie_text = cookie_texts[0] try: cookies = http.cookies.SimpleCookie( cookie_text ) if 'session_key' in cookies: # Morsel, for real, ha ha ha morsel = cookies[ 'session_key' ] session_key_hex = morsel.value session_key = bytes.fromhex( session_key_hex ) except: raise HydrusExceptions.BadRequestException( 'Problem parsing cookies for Session Cookie!' ) if session_key is None: access_key = self._parseHydrusNetworkAccessKey( request, key_required = False ) if access_key is None: raise HydrusExceptions.MissingCredentialsException( 'No credentials found in request!' ) else: account = HG.server_controller.server_session_manager.GetAccountFromAccessKey( self._service_key, access_key ) else: account = HG.server_controller.server_session_manager.GetAccount( self._service_key, session_key ) request.hydrus_account = account return request def _checkAccount( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckFunctional() return request def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): raise NotImplementedError() def _checkBandwidth( self, request: HydrusServerRequest.HydrusRequest ): if not self._service.BandwidthOK(): raise HydrusExceptions.BandwidthException( 'This service has run out of bandwidth. Please try again later.' ) if not HG.server_controller.ServerBandwidthOK(): raise HydrusExceptions.BandwidthException( 'This server has run out of bandwidth. Please try again later.' ) def _reportDataUsed( self, request, num_bytes ): HydrusResourceHydrusNetwork._reportDataUsed( self, request, num_bytes ) account = request.hydrus_account if account is not None: account.ReportDataUsed( num_bytes ) def _reportRequestUsed( self, request: HydrusServerRequest.HydrusRequest ): HydrusResourceHydrusNetwork._reportRequestUsed( self, request ) account = request.hydrus_account if account is not None: account.ReportRequestUsed() class HydrusResourceRestrictedAccount( HydrusResourceRestricted ): def _checkAccount( self, request: HydrusServerRequest.HydrusRequest ): # you can always fetch your account (e.g. to be notified that you are banned!) return request def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # you can always fetch your account pass def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): account = request.hydrus_account body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'account' : account } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedOptions( HydrusResourceRestricted ): def _checkAccount( self, request: HydrusServerRequest.HydrusRequest ): # you can always fetch the options return request def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # you can always fetch the options pass def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): service_options = self._service.GetServiceOptions() body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'service_options' : service_options } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedOptionsModify( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_OPTIONS, HC.PERMISSION_ACTION_MODERATE ) class HydrusResourceRestrictedOptionsModifyUpdatePeriod( HydrusResourceRestrictedOptionsModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): update_period = request.parsed_request_args[ 'update_period' ] if update_period < HydrusNetwork.MIN_UPDATE_PERIOD: raise HydrusExceptions.BadRequestException( 'The update period was too low. It needs to be at least {}.'.format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MIN_UPDATE_PERIOD ) ) ) if update_period > HydrusNetwork.MAX_UPDATE_PERIOD: raise HydrusExceptions.BadRequestException( 'The update period was too high. It needs to be lower than {}.'.format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MAX_UPDATE_PERIOD ) ) ) self._service.SetUpdatePeriod( update_period ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountModify( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_ACCOUNTS, HC.PERMISSION_ACTION_MODERATE ) class HydrusResourceRestrictedAccountInfo( HydrusResourceRestrictedAccountModify ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) subject_account = HG.server_controller.Read( 'account', self._service_key, subject_account_key ) account_info = HG.server_controller.Read( 'account_info', self._service_key, request.hydrus_account, subject_account ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'account_info' : account_info } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedAccountModifyAccountType( HydrusResourceRestrictedAccountModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) if 'account_type_key' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account type key, but did not get one!' ) account_type_key = request.parsed_request_args[ 'account_type_key' ] HG.server_controller.WriteSynchronous( 'modify_account_account_type', self._service_key, request.hydrus_account, subject_account_key, account_type_key ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountModifyBan( HydrusResourceRestrictedAccountModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) if 'reason' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a reason for the ban, but did not get one!' ) if 'expires' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a new expiration timestamp, but did not get one!' ) reason = request.parsed_request_args[ 'reason' ] if not isinstance( reason, str ): raise HydrusExceptions.BadRequestException( 'The given ban reason was not a string!' ) expires = request.parsed_request_args[ 'expires' ] expires_is_none = expires is None expires_is_positive_integer = isinstance( expires, int ) and expires > 0 expires_is_valid = expires_is_none or expires_is_positive_integer if not expires_is_valid: raise HydrusExceptions.BadRequestException( 'The given expiration timestamp was not null or an integer!' ) HG.server_controller.WriteSynchronous( 'modify_account_ban', self._service_key, request.hydrus_account, subject_account_key, reason, expires ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountModifyExpires( HydrusResourceRestrictedAccountModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) if 'expires' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a new expiration timestamp, but did not get one!' ) expires = request.parsed_request_args[ 'expires' ] expires_is_none = expires is None expires_is_positive_integer = isinstance( expires, int ) and expires > 0 expires_is_valid = expires_is_none or expires_is_positive_integer if not expires_is_valid: raise HydrusExceptions.BadRequestException( 'The given expiration timestamp was not None or an integer!' ) HG.server_controller.WriteSynchronous( 'modify_account_expires', self._service_key, request.hydrus_account, subject_account_key, expires ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountModifySetMessage( HydrusResourceRestrictedAccountModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) if 'message' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a new message, but did not get one!' ) message = request.parsed_request_args[ 'message' ] if not isinstance( message, str ): raise HydrusExceptions.BadRequestException( 'The given message was not a string!' ) HG.server_controller.WriteSynchronous( 'modify_account_set_message', self._service_key, request.hydrus_account, subject_account_key, message ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountModifyUnban( HydrusResourceRestrictedAccountModify ): def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) HG.server_controller.WriteSynchronous( 'modify_account_unban', self._service_key, request.hydrus_account, subject_account_key ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedAccountOtherAccount( HydrusResourceRestrictedAccountModify ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account identifier for the subject, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() try: subject_account = HG.server_controller.Read( 'account', self._service_key, subject_account_key ) except HydrusExceptions.InsufficientCredentialsException as e: raise HydrusExceptions.NotFoundException( e ) elif subject_identifier.HasContent(): subject_content = subject_identifier.GetContent() subject_account = HG.server_controller.Read( 'account_from_content', self._service_key, subject_content ) else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key or content!' ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'account' : subject_account } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedIP( HydrusResourceRestrictedAccountModify ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): hash = request.parsed_request_args[ 'hash' ] ( ip, timestamp ) = HG.server_controller.Read( 'ip', self._service_key, request.hydrus_account, hash ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'ip' : ip, 'timestamp' : timestamp } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedAllAccounts( HydrusResourceRestrictedAccountModify ): def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): accounts = HG.server_controller.Read( 'all_accounts', self._service_key, request.hydrus_account ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'accounts' : accounts } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedAccountTypes( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): if request.IsGET(): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_ACCOUNTS, HC.PERMISSION_ACTION_CREATE ) elif request.IsPOST(): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_ACCOUNT_TYPES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): account_types = HG.server_controller.Read( 'account_types', self._service_key, request.hydrus_account ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'account_types' : account_types } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): account_types = request.parsed_request_args[ 'account_types' ] deletee_account_type_keys_to_new_account_type_keys = request.parsed_request_args[ 'deletee_account_type_keys_to_new_account_type_keys' ] HG.server_controller.WriteSynchronous( 'account_types', self._service_key, request.hydrus_account, account_types, deletee_account_type_keys_to_new_account_type_keys ) HG.server_controller.server_session_manager.RefreshAccounts( self._service_key ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedBackup( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): HG.server_controller.Write( 'backup' ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedLockOn( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): locked = HG.server_busy.acquire( False ) # pylint: disable=E1111 if not locked: raise HydrusExceptions.BadRequestException( 'The server was already locked!' ) HG.server_controller.db.PauseAndDisconnect( True ) # shut down db, wait until it is done? response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedLockOff( HydrusResourceRestricted ): BLOCKED_WHEN_BUSY = False def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): try: HG.server_busy.release() except threading.ThreadError: raise HydrusExceptions.BadRequestException( 'The server is not busy!' ) HG.server_controller.db.PauseAndDisconnect( False ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedNumPetitions( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # further permissions checked in the db request.hydrus_account.CheckAtLeastOnePermission( [ ( content_type, HC.PERMISSION_ACTION_MODERATE ) for content_type in HC.REPOSITORY_CONTENT_TYPES ] ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): # cache this petition_count_info = HG.server_controller.Read( 'num_petitions', self._service_key, request.hydrus_account ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'num_petitions' : petition_count_info } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedPetitionSummaryList( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): content_type = request.parsed_request_args[ 'content_type' ] request.hydrus_account.CheckPermission( content_type, HC.PERMISSION_ACTION_MODERATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): # fetch cached summary list # ( account_key, reason, size of petition ) petition_summary_list = [] body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'petition_summary_list' : petition_summary_list } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedPetition( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): content_type = request.parsed_request_args[ 'content_type' ] request.hydrus_account.CheckPermission( content_type, HC.PERMISSION_ACTION_MODERATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): # rewangle this to take an id from the summary list. probably ( account_key, reason_id ) # and combine petitioned and pending into the same petition content_type = request.parsed_request_args[ 'content_type' ] status = request.parsed_request_args[ 'status' ] petition = HG.server_controller.Read( 'petition', self._service_key, request.hydrus_account, content_type, status ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'petition' : petition } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedRegistrationKeys( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_ACCOUNTS, HC.PERMISSION_ACTION_CREATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): num = request.parsed_request_args[ 'num' ] account_type_key = request.parsed_request_args[ 'account_type_key' ] if 'expires' in request.parsed_request_args: expires = request.parsed_request_args[ 'expires' ] else: expires = None registration_keys = HG.server_controller.Read( 'registration_keys', self._service_key, request.hydrus_account, num, account_type_key, expires ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'registration_keys' : registration_keys } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedRepositoryFile( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # everyone with a functional account can read files if request.IsPOST(): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_FILES, HC.PERMISSION_ACTION_CREATE ) def _DecompressionBombsOK( self, request: HydrusServerRequest.HydrusRequest ): if request.hydrus_account is None: return False else: return request.hydrus_account.HasPermission( HC.CONTENT_TYPE_ACCOUNTS, HC.PERMISSION_ACTION_CREATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): self._checkBandwidth( request ) # no permission check as any functional account can get files hash = request.parsed_request_args[ 'hash' ] ( valid, mime ) = HG.server_controller.Read( 'service_has_file', self._service_key, hash ) if not valid: raise HydrusExceptions.NotFoundException( 'File not found on this service!' ) path = ServerFiles.GetFilePath( hash ) response_context = HydrusServerResources.ResponseContext( 200, mime = mime, path = path ) return response_context def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): file_dict = request.parsed_request_args if self._service.LogUploaderIPs(): file_dict[ 'ip' ] = request.getClientIP() timestamp = self._service.GetMetadata().GetNextUpdateBegin() + 1 HG.server_controller.WriteSynchronous( 'file', self._service, request.hydrus_account, file_dict, timestamp ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedRepositoryThumbnail( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # everyone with a functional account can read thumbs pass def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): self._checkBandwidth( request ) # no permission check as any functional account can get thumbnails hash = request.parsed_request_args[ 'hash' ] ( valid, mime ) = HG.server_controller.Read( 'service_has_file', self._service_key, hash ) if not valid: raise HydrusExceptions.NotFoundException( 'Thumbnail not found on this service!' ) if mime not in HC.MIMES_WITH_THUMBNAILS: raise HydrusExceptions.NotFoundException( 'That mime should not have a thumbnail!' ) path = ServerFiles.GetThumbnailPath( hash ) response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_OCTET_STREAM, path = path ) return response_context class HydrusResourceRestrictedServices( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): services = HG.server_controller.Read( 'services_from_account', request.hydrus_account ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'services' : services } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): services = request.parsed_request_args[ 'services' ] unique_ports = { service.GetPort() for service in services } if len( unique_ports ) < len( services ): raise HydrusExceptions.BadRequestException( 'It looks like some of those services share ports! Please give them unique ports!' ) with HG.dirty_object_lock: HG.server_controller.SetServices( services ) service_keys_to_access_keys = HG.server_controller.WriteSynchronous( 'services', request.hydrus_account, services ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'service_keys_to_access_keys' : service_keys_to_access_keys } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedUpdate( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): # everyone with a functional account can read updates if request.IsPOST(): # further permissions checked in the db request.hydrus_account.CheckAtLeastOnePermission( [ ( content_type, HC.PERMISSION_ACTION_PETITION ) for content_type in HC.REPOSITORY_CONTENT_TYPES ] ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): self._checkBandwidth( request ) # no permissions check as any functional account can get updates update_hash = request.parsed_request_args[ 'update_hash' ] if not self._service.HasUpdateHash( update_hash ): raise HydrusExceptions.NotFoundException( 'This update hash does not exist on this service!' ) path = ServerFiles.GetFilePath( update_hash ) response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_OCTET_STREAM, path = path ) return response_context def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): client_to_server_update = request.parsed_request_args[ 'client_to_server_update' ] timestamp = self._service.GetMetadata().GetNextUpdateBegin() + 1 HG.server_controller.WriteSynchronous( 'update', self._service_key, request.hydrus_account, client_to_server_update, timestamp ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context class HydrusResourceRestrictedImmediateUpdate( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckAtLeastOnePermission( [ ( content_type, HC.PERMISSION_ACTION_MODERATE ) for content_type in HC.REPOSITORY_CONTENT_TYPES ] ) def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): updates = HG.server_controller.Read( 'immediate_update', self._service_key, request.hydrus_account ) updates = HydrusSerialisable.SerialisableList( updates ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'updates' : updates } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedMetadataUpdate( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): pass # everyone with a functional account can get metadata slices def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ): since = request.parsed_request_args[ 'since' ] metadata_slice = self._service.GetMetadataSlice( since ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( { 'metadata_slice' : metadata_slice } ) response_context = HydrusServerResources.ResponseContext( 200, body = body ) return response_context class HydrusResourceRestrictedVacuum( HydrusResourceRestricted ): def _checkAccountPermissions( self, request: HydrusServerRequest.HydrusRequest ): request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_MODERATE ) def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): HG.server_controller.Write( 'vacuum' ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context