txhttputil 1.3.0__tar.gz → 1.4.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. txhttputil-1.4.7/PKG-INFO +47 -0
  2. txhttputil-1.4.7/pyproject.toml +40 -0
  3. txhttputil-1.4.7/setup.cfg +4 -0
  4. txhttputil-1.4.7/txhttputil/__init__.py +3 -0
  5. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/AuthSessionWrapper.py +26 -7
  6. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/BasicResource.py +9 -1
  7. txhttputil-1.4.7/txhttputil/site/BasicResourceTest.py +104 -0
  8. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/FileUnderlayResource.py +23 -16
  9. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/FileUnderlayResourceTest.py +12 -2
  10. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/RootResource.py +6 -4
  11. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/SiteUtil.py +2 -3
  12. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/StaticFileResource.py +2 -2
  13. txhttputil-1.4.7/txhttputil.egg-info/PKG-INFO +47 -0
  14. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil.egg-info/SOURCES.txt +1 -1
  15. txhttputil-1.3.0/PKG-INFO +0 -18
  16. txhttputil-1.3.0/pyproject.toml +0 -41
  17. txhttputil-1.3.0/setup.cfg +0 -7
  18. txhttputil-1.3.0/txhttputil/__init__.py +0 -3
  19. txhttputil-1.3.0/txhttputil.egg-info/PKG-INFO +0 -18
  20. {txhttputil-1.3.0 → txhttputil-1.4.7}/LICENSE +0 -0
  21. {txhttputil-1.3.0 → txhttputil-1.4.7}/README.md +0 -0
  22. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/downloader/HttpFileDownloader.py +0 -0
  23. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/downloader/HttpResourceProxy.py +0 -0
  24. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/downloader/__init__.py +0 -0
  25. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/login_page/LoginElement.py +0 -0
  26. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/login_page/LoginTemplate.xml +0 -0
  27. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/login_page/__init__.py +0 -0
  28. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/AuthCredentials.py +0 -0
  29. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/AuthResource.py +0 -0
  30. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/AuthUserDetails.py +0 -0
  31. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/FileUploadRequest.py +1 -1
  32. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/RedirectToHttpsResource.py +0 -0
  33. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/RedirectionRule.py +0 -0
  34. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/ResourceCreator.py +0 -0
  35. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/RootSiteTest.py +0 -0
  36. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/site/__init__.py +0 -0
  37. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/util/DeferUtil.py +0 -0
  38. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/util/ModuleUtil.py +0 -0
  39. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/util/PemUtil.py +0 -0
  40. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/util/SslUtil.py +0 -0
  41. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil/util/__init__.py +0 -0
  42. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil.egg-info/dependency_links.txt +0 -0
  43. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil.egg-info/requires.txt +0 -0
  44. {txhttputil-1.3.0 → txhttputil-1.4.7}/txhttputil.egg-info/top_level.txt +0 -0
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.1
2
+ Name: txhttputil
3
+ Version: 1.4.7
4
+ Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
+ Author-email: Synerty <contact@synerty.com>
6
+ Project-URL: Homepage, https://gitlab.synerty.com/peek/util/txhttputil
7
+ Keywords: twisted,resource,file,download,synerty
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: pytz
16
+ Requires-Dist: txwebsocket>=1.0.1
17
+ Requires-Dist: filetype
18
+ Requires-Dist: pem
19
+ Requires-Dist: pytmpdir
20
+ Requires-Dist: treelib>=1.6.4
21
+ Requires-Dist: cryptography
22
+ Requires-Dist: pyOpenSSL
23
+
24
+ # TxHttpUtil
25
+ Synerty utility classes for serving a static site with twisted.web with user permissions.
26
+
27
+ Whats of interest?
28
+
29
+ * Protected resource with simple form login - Not suitable for public networks at this
30
+ stage
31
+ * A resource that underlays a multi level file system search under a standard twisted
32
+ Resource.putChild type resource tree.
33
+ * Twisted HTTP File Downloader
34
+ * Consistent request data, providing a Bytes IO like oboject and switching to a
35
+ NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
36
+ * Support for single page applications
37
+
38
+ # TODO
39
+
40
+ Unit tests for :
41
+ * Creating resource trees
42
+ * Getting resources from the resource tree
43
+ * Getting files from an underlay resource with two underlays
44
+ * Downloading files with the
45
+ * Logging into the test site (Using Seleneium/Chrome WebDriver)
46
+ * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
47
+ from BytesIO
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools<70.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta:__legacy__"
4
+
5
+ [project]
6
+ name = "txhttputil"
7
+ version = "1.4.7"
8
+ description = "Synerty utility classes for serving a static site with twisted.web with user permissions."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ keywords = ["twisted", "resource", "file", "download", "synerty"]
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3.9",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12"
17
+ ]
18
+ dependencies = [
19
+ "pytz",
20
+ "txwebsocket>=1.0.1",
21
+ "filetype",
22
+ "pem",
23
+ "pytmpdir",
24
+ "treelib>=1.6.4",
25
+ "cryptography",
26
+ "pyOpenSSL",
27
+ ]
28
+ authors = [
29
+ {name = "Synerty", email = "contact@synerty.com"}
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://gitlab.synerty.com/peek/util/txhttputil"
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["."]
37
+ include = ["txhttputil*"]
38
+
39
+ [tool.setuptools.package-data]
40
+ "txhttputil.login_page" = ["*.xml"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+
2
+
3
+ __version__ = '1.4.7'
@@ -4,16 +4,16 @@ from datetime import datetime
4
4
  import pytz
5
5
  from twisted.web.resource import IResource, ErrorPage
6
6
  from twisted.web.util import DeferredResource
7
- from zope.interface import implementer
8
-
9
7
  from txhttputil.site.AuthCredentials import AuthCredentials
10
8
  from txhttputil.site.AuthUserDetails import IUserSession
11
9
  from txhttputil.site.BasicResource import BasicResource
10
+ from zope.interface import implementer
11
+
12
12
  from .AuthResource import LoginResource, LoginSucceededResource
13
13
 
14
14
  logger = logging.getLogger(name=__name__)
15
15
 
16
- __author__ = 'synerty'
16
+ __author__ = "synerty"
17
17
 
18
18
 
19
19
  @implementer(IResource)
@@ -24,11 +24,15 @@ class FormBasedAuthSessionWrapper(object):
24
24
 
25
25
  isLeaf = False
26
26
 
27
- def __init__(self,
28
- siteRootResource: BasicResource,
29
- credentialChecker: AuthCredentials):
27
+ def __init__(
28
+ self,
29
+ siteRootResource: BasicResource,
30
+ credentialChecker: AuthCredentials,
31
+ allowedIpsList=None,
32
+ ):
30
33
  self._siteRootResource = siteRootResource
31
34
  self._credentialChecker = credentialChecker
35
+ self._allowedIpsList = allowedIpsList
32
36
 
33
37
  def _authorizedResource(self, request):
34
38
  """
@@ -67,7 +71,7 @@ class FormBasedAuthSessionWrapper(object):
67
71
 
68
72
  a = request.args
69
73
  if b"username" in a and b"password" in a:
70
- user = a[b'username'][0]
74
+ user = a[b"username"][0]
71
75
  pass_ = a[b"password"][0]
72
76
 
73
77
  deferred = self._credentialChecker.check(user, pass_)
@@ -103,6 +107,13 @@ class FormBasedAuthSessionWrapper(object):
103
107
  possible, and render it. Otherwise, perhaps render an error page
104
108
  requiring authorization or describing an internal server failure.
105
109
  """
110
+ # Check IP filtering if configured
111
+ if self._allowedIpsList is not None:
112
+ clientIp = request.getClientAddress().host
113
+ if clientIp not in self._allowedIpsList:
114
+ request.setResponseCode(403)
115
+ return b"Forbidden: IP address not allowed"
116
+
106
117
  return self._authorizedResource(request).render(request)
107
118
 
108
119
  def getChildWithDefault(self, path, request):
@@ -113,6 +124,14 @@ class FormBasedAuthSessionWrapper(object):
113
124
  be returned, essentially halting further dispatch on the wrapped
114
125
  resource and all children
115
126
  """
127
+ # Check IP filtering if configured
128
+ if self._allowedIpsList is not None:
129
+ clientIp = request.getClientAddress().host
130
+ if clientIp not in self._allowedIpsList:
131
+ from twisted.web.resource import ErrorPage
132
+
133
+ return ErrorPage(403, b"Forbidden", b"IP address not allowed")
134
+
116
135
  # Don't consume any segments of the request - this class should be
117
136
  # transparent!
118
137
  request.postpath.insert(0, request.prepath.pop())
@@ -37,11 +37,12 @@ class BasicResource:
37
37
  server = None
38
38
  isLeaf = False
39
39
 
40
- def __init__(self):
40
+ def __init__(self, allowedIpsList=None):
41
41
  """
42
42
  Initialize.
43
43
  """
44
44
  self._children = {}
45
+ self._allowedIpsList = allowedIpsList
45
46
 
46
47
  def getChildWithDefault(self, path, request):
47
48
  """ Get Child With Default
@@ -120,6 +121,13 @@ class BasicResource:
120
121
  del self._children[path]
121
122
 
122
123
  def render(self, request):
124
+ # Check IP filtering if configured
125
+ if self._allowedIpsList is not None:
126
+ clientIp = request.getClientAddress().host
127
+ if clientIp not in self._allowedIpsList:
128
+ request.setResponseCode(403)
129
+ return b'Forbidden: IP address not allowed'
130
+
123
131
  # Optionally, Do some checking with userSession.userDetails.group
124
132
  # userSession = IUserSession(request.getSession())
125
133
 
@@ -0,0 +1,104 @@
1
+ import logging
2
+
3
+ from twisted.trial import unittest
4
+ from twisted.web.resource import NoResource
5
+ from twisted.web.test.requesthelper import DummyRequest
6
+ from txhttputil.site.BasicResource import BasicResource
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class MockAddress:
12
+ def __init__(self, host):
13
+ self.host = host
14
+
15
+
16
+ class TestBasicResource(BasicResource):
17
+ def render_GET(self, request):
18
+ return b"GET response"
19
+
20
+ def render_POST(self, request):
21
+ return b"POST response"
22
+
23
+
24
+ class BasicResourceTest(unittest.TestCase):
25
+
26
+ def setUp(self):
27
+ self.resource = TestBasicResource()
28
+
29
+ def testBasicGetChild(self):
30
+ child = self.resource.getChild(b"nonexistent", None)
31
+ self.assertIsInstance(child, NoResource)
32
+
33
+ def testPutAndGetChild(self):
34
+ childResource = TestBasicResource()
35
+ self.resource.putChild(b"child", childResource)
36
+
37
+ retrievedChild = self.resource.getChild(b"child", None)
38
+ self.assertEqual(retrievedChild, childResource)
39
+
40
+ def testDeleteChild(self):
41
+ childResource = TestBasicResource()
42
+ self.resource.putChild(b"child", childResource)
43
+
44
+ self.resource.deleteChild(b"child")
45
+
46
+ retrievedChild = self.resource.getChild(b"child", None)
47
+ self.assertIsInstance(retrievedChild, NoResource)
48
+
49
+ def testRenderGetMethod(self):
50
+ request = DummyRequest([])
51
+ request.method = b"GET"
52
+
53
+ response = self.resource.render(request)
54
+ self.assertEqual(response, b"GET response")
55
+
56
+ def testRenderPostMethod(self):
57
+ request = DummyRequest([])
58
+ request.method = b"POST"
59
+
60
+ response = self.resource.render(request)
61
+ self.assertEqual(response, b"POST response")
62
+
63
+ def testIpFilteringAllowed(self):
64
+ allowedIps = ["127.0.0.1", "192.168.1.100"]
65
+ resource = TestBasicResource(allowedIpsList=allowedIps)
66
+
67
+ request = DummyRequest([])
68
+ request.method = b"GET"
69
+ request.getClientAddress = lambda: MockAddress("127.0.0.1")
70
+
71
+ response = resource.render(request)
72
+ self.assertEqual(response, b"GET response")
73
+
74
+ def testIpFilteringBlocked(self):
75
+ allowedIps = ["127.0.0.1", "192.168.1.100"]
76
+ resource = TestBasicResource(allowedIpsList=allowedIps)
77
+
78
+ request = DummyRequest([])
79
+ request.method = b"GET"
80
+ request.getClientAddress = lambda: MockAddress("10.0.0.1")
81
+
82
+ response = resource.render(request)
83
+ self.assertEqual(response, b"Forbidden: IP address not allowed")
84
+ self.assertEqual(request.responseCode, 403)
85
+
86
+ def testIpFilteringDisabled(self):
87
+ resource = TestBasicResource(allowedIpsList=None)
88
+
89
+ request = DummyRequest([])
90
+ request.method = b"GET"
91
+ request.getClientAddress = lambda: MockAddress("10.0.0.1")
92
+
93
+ response = resource.render(request)
94
+ self.assertEqual(response, b"GET response")
95
+
96
+
97
+ if __name__ == "__main__":
98
+ from twisted.trial import runner, reporter
99
+ import sys
100
+
101
+ trialRunner = runner.TrialRunner(reporter.VerboseTextReporter)
102
+ suite = runner.TestLoader().loadClass(BasicResourceTest)
103
+ result = trialRunner.run(suite)
104
+ sys.exit(not result.wasSuccessful())
@@ -1,10 +1,9 @@
1
1
  import logging
2
- from typing import Union, List
3
-
4
2
  import os
3
+ from typing import Union
4
+
5
5
  from twisted.web.resource import NoResource
6
6
  from twisted.web.util import Redirect
7
-
8
7
  from txhttputil.site.BasicResource import BasicResource
9
8
  from txhttputil.site.RedirectionRule import RedirectionRule
10
9
 
@@ -17,12 +16,12 @@ mimetypes.init()
17
16
 
18
17
  def get_extensions_for_type(general_type):
19
18
  for ext in mimetypes.types_map:
20
- if mimetypes.types_map[ext].split('/')[0] == general_type:
19
+ if mimetypes.types_map[ext].split("/")[0] == general_type:
21
20
  yield ext
22
21
 
23
22
 
24
- IMAGE_EXTENSIONS = list(get_extensions_for_type('image'))
25
- FONT_EXTENSIONS = list(get_extensions_for_type('font'))
23
+ IMAGE_EXTENSIONS = list(get_extensions_for_type("image"))
24
+ FONT_EXTENSIONS = list(get_extensions_for_type("font"))
26
25
 
27
26
 
28
27
  class SinglePageAppConfig:
@@ -31,7 +30,9 @@ class SinglePageAppConfig:
31
30
 
32
31
  for kw, arg in kwargs.items():
33
32
  if not hasattr(self, kw):
34
- raise KeyError("%s is not an argument for %s" % (kw, self.__class__))
33
+ raise KeyError(
34
+ "%s is not an argument for %s" % (kw, self.__class__)
35
+ )
35
36
  setattr(self, kw, arg)
36
37
 
37
38
 
@@ -46,14 +47,14 @@ class FileUnderlayResource(BasicResource):
46
47
 
47
48
  """
48
49
 
49
- acceptedExtensions = ['.js', '.css', '.html', '.xml']
50
+ acceptedExtensions = [".js", ".css", ".html", ".xml"]
50
51
  acceptedExtensions += FONT_EXTENSIONS
51
52
  acceptedExtensions += IMAGE_EXTENSIONS
52
53
 
53
54
  # TODO Implement accepted extensions
54
55
 
55
- def __init__(self):
56
- BasicResource.__init__(self)
56
+ def __init__(self, allowedIpsList=None):
57
+ BasicResource.__init__(self, allowedIpsList)
57
58
 
58
59
  self._fileSystemRoots = []
59
60
  self._singlePageAppConfig = None
@@ -72,7 +73,7 @@ class FileUnderlayResource(BasicResource):
72
73
  if filePath:
73
74
  return self._gzipIfRequired(StaticFileResource(filePath))
74
75
 
75
- if not resourcePath or not '.' in os.path.basename(resourcePath):
76
+ if not resourcePath or not "." in os.path.basename(resourcePath):
76
77
  singlePageResource = self._getSinglePageAppResource()
77
78
  if singlePageResource:
78
79
  return singlePageResource
@@ -86,7 +87,9 @@ class FileUnderlayResource(BasicResource):
86
87
  self._fileSystemRoots.append(fileSystemRoot)
87
88
 
88
89
  def enableSinglePageApplication(self, indexHtmlPath="index.html"):
89
- self._singlePageAppConfig = SinglePageAppConfig(indexHtmlPath=indexHtmlPath)
90
+ self._singlePageAppConfig = SinglePageAppConfig(
91
+ indexHtmlPath=indexHtmlPath
92
+ )
90
93
 
91
94
  def getRealFilePath(self, resourcePath: str) -> Union[str, None]:
92
95
  if not resourcePath:
@@ -96,8 +99,11 @@ class FileUnderlayResource(BasicResource):
96
99
  realFilePath = os.path.join(rootDir, resourcePath)
97
100
 
98
101
  if os.path.isdir(realFilePath):
99
- logger.debug("Resource path %s is a directory %s",
100
- resourcePath, realFilePath)
102
+ logger.debug(
103
+ "Resource path %s is a directory %s",
104
+ resourcePath,
105
+ realFilePath,
106
+ )
101
107
  continue
102
108
 
103
109
  if os.path.isfile(realFilePath):
@@ -111,10 +117,11 @@ class FileUnderlayResource(BasicResource):
111
117
  filePath = self.getRealFilePath(self._singlePageAppConfig.indexHtmlPath)
112
118
  if filePath:
113
119
  from txhttputil.site.StaticFileResource import StaticFileResource
120
+
114
121
  return self._gzipIfRequired(StaticFileResource(filePath))
115
122
 
116
123
  def render_GET(self, request):
117
- """ Render Get
124
+ """Render Get
118
125
 
119
126
  If we're being redered then that means we've exactly matched the resurce path.
120
127
  IE, The path is looking for a directory, not a file.
@@ -131,4 +138,4 @@ class FileUnderlayResource(BasicResource):
131
138
  def getChild(self, path, request):
132
139
  if request.uri in self._redirections.keys():
133
140
  return Redirect(self._redirections[request.uri])
134
- return super().getChild(path, request)
141
+ return super().getChild(path, request)
@@ -5,11 +5,11 @@ from twisted.internet import reactor
5
5
  from twisted.trial import unittest
6
6
  from twisted.web import server
7
7
  from twisted.web.resource import ErrorPage
8
-
9
- import txhttputil
10
8
  from txhttputil.downloader.HttpFileDownloader import HttpFileDownloader
11
9
  from txhttputil.site.FileUnderlayResource import FileUnderlayResource
12
10
 
11
+ import txhttputil
12
+
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
@@ -72,3 +72,13 @@ class FileUnderlayResourceTest(unittest.TestCase):
72
72
  d = HttpFileDownloader(self.sitePath + fileName).run()
73
73
  d.addCallback(self._checkDownloadedResource, fileName=realPath)
74
74
  return d
75
+
76
+
77
+ if __name__ == "__main__":
78
+ from twisted.trial import runner, reporter
79
+ import sys
80
+
81
+ trialRunner = runner.TrialRunner(reporter.VerboseTextReporter)
82
+ suite = runner.TestLoader().loadClass(FileUnderlayResourceTest)
83
+ result = trialRunner.run(suite)
84
+ sys.exit(not result.wasSuccessful())
@@ -7,21 +7,23 @@
7
7
  * Support : support@synerty.com
8
8
  """
9
9
 
10
+ from txhttputil.site.AuthUserDetails import AuthUserDetails
10
11
  from txhttputil.site.ResourceUtil import RESOURCES
11
- from txhttputil.site.StaticFileResource import StaticFileResource
12
12
  from txhttputil.site.StaticFileMultiPath import StaticFileMultiPath
13
- from txhttputil.site.AuthUserDetails import AuthUserDetails
13
+ from txhttputil.site.StaticFileResource import StaticFileResource
14
14
 
15
15
 
16
16
  class RootResource(StaticFileResource):
17
- """ Root Resource
17
+ """Root Resource
18
18
 
19
19
  This resource is the root or subroot of a resource tree.
20
20
  It first looks for resources created with "createRoot
21
21
  """
22
22
 
23
23
 
24
- def createRootResource(userAccess: AuthUserDetails, staticFileRoot: StaticFileMultiPath):
24
+ def createRootResource(
25
+ userAccess: AuthUserDetails, staticFileRoot: StaticFileMultiPath
26
+ ):
25
27
  rootResource = RootResource(userAccess, staticFileRoot=staticFileRoot)
26
28
  callResourceCreators(RESOURCES, rootResource, userAccess)
27
29
 
@@ -14,7 +14,6 @@ from typing import Optional
14
14
  from twisted.internet import reactor
15
15
  from twisted.internet._sslverify import trustRootFromCertificates
16
16
  from twisted.web import server
17
-
18
17
  from txhttputil.login_page.LoginElement import LoginElement
19
18
  from txhttputil.site.AuthCredentials import (
20
19
  AllowAllAuthCredentials,
@@ -23,8 +22,6 @@ from txhttputil.site.AuthCredentials import (
23
22
  from txhttputil.site.AuthSessionWrapper import FormBasedAuthSessionWrapper
24
23
  from txhttputil.site.FileUploadRequest import FileUploadRequest
25
24
  from txhttputil.site.RedirectToHttpsResource import RedirectToHttpsResource
26
- from txwebsocket.txws import WebSocketUpgradeHTTPChannel
27
-
28
25
  from txhttputil.util.PemUtil import (
29
26
  PEM_CHECK_TYPE,
30
27
  parseTrustRootFromBundle,
@@ -36,6 +33,8 @@ from txhttputil.util.SslUtil import (
36
33
  buildCertificateOptionsForTwisted,
37
34
  )
38
35
 
36
+ from txwebsocket.txws import WebSocketUpgradeHTTPChannel
37
+
39
38
  logger = logging.getLogger(__name__)
40
39
 
41
40
 
@@ -39,9 +39,9 @@ class StaticFileResource(BasicResource):
39
39
  ]
40
40
 
41
41
  def __init__(
42
- self, filePath: str, expireMinutes: int = 30, chunkSize: int = 128000
42
+ self, filePath: str, expireMinutes: int = 30, chunkSize: int = 128000, allowedIpsList=None
43
43
  ):
44
- BasicResource.__init__(self)
44
+ BasicResource.__init__(self, allowedIpsList)
45
45
  self._filePath = filePath
46
46
  self.cancelDownload = False
47
47
  self.expireMinutes = expireMinutes
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.1
2
+ Name: txhttputil
3
+ Version: 1.4.7
4
+ Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
+ Author-email: Synerty <contact@synerty.com>
6
+ Project-URL: Homepage, https://gitlab.synerty.com/peek/util/txhttputil
7
+ Keywords: twisted,resource,file,download,synerty
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: pytz
16
+ Requires-Dist: txwebsocket>=1.0.1
17
+ Requires-Dist: filetype
18
+ Requires-Dist: pem
19
+ Requires-Dist: pytmpdir
20
+ Requires-Dist: treelib>=1.6.4
21
+ Requires-Dist: cryptography
22
+ Requires-Dist: pyOpenSSL
23
+
24
+ # TxHttpUtil
25
+ Synerty utility classes for serving a static site with twisted.web with user permissions.
26
+
27
+ Whats of interest?
28
+
29
+ * Protected resource with simple form login - Not suitable for public networks at this
30
+ stage
31
+ * A resource that underlays a multi level file system search under a standard twisted
32
+ Resource.putChild type resource tree.
33
+ * Twisted HTTP File Downloader
34
+ * Consistent request data, providing a Bytes IO like oboject and switching to a
35
+ NamedTemporaryFile if fileno, or name is called, or the data exceeds 5mb.
36
+ * Support for single page applications
37
+
38
+ # TODO
39
+
40
+ Unit tests for :
41
+ * Creating resource trees
42
+ * Getting resources from the resource tree
43
+ * Getting files from an underlay resource with two underlays
44
+ * Downloading files with the
45
+ * Logging into the test site (Using Seleneium/Chrome WebDriver)
46
+ * Test uploading data under 5mb and over 5mb to and auto switching to NamedTemporaryFile
47
+ from BytesIO
@@ -1,7 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- setup.cfg
5
4
  txhttputil/__init__.py
6
5
  txhttputil.egg-info/PKG-INFO
7
6
  txhttputil.egg-info/SOURCES.txt
@@ -19,6 +18,7 @@ txhttputil/site/AuthResource.py
19
18
  txhttputil/site/AuthSessionWrapper.py
20
19
  txhttputil/site/AuthUserDetails.py
21
20
  txhttputil/site/BasicResource.py
21
+ txhttputil/site/BasicResourceTest.py
22
22
  txhttputil/site/FileUnderlayResource.py
23
23
  txhttputil/site/FileUnderlayResourceTest.py
24
24
  txhttputil/site/FileUploadRequest.py
txhttputil-1.3.0/PKG-INFO DELETED
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: txhttputil
3
- Version: 1.3.0
4
- Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
- Author-email: Synerty <contact@synerty.com>
6
- Project-URL: Homepage, https://github.com/Synerty/txhttputil
7
- Project-URL: Download, https://github.com/Synerty/txhttputil/tarball/1.2.11
8
- Keywords: twisted,resource,file,download,synerty
9
- Classifier: Programming Language :: Python :: 3.9
10
- License-File: LICENSE
11
- Requires-Dist: pytz
12
- Requires-Dist: txwebsocket>=1.0.1
13
- Requires-Dist: filetype
14
- Requires-Dist: pem
15
- Requires-Dist: pytmpdir
16
- Requires-Dist: treelib>=1.6.4
17
- Requires-Dist: cryptography
18
- Requires-Dist: pyOpenSSL
@@ -1,41 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.2"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "txhttputil"
7
- version = "1.3.0"
8
- authors = [{name = "Synerty", email = "contact@synerty.com"}]
9
- description = "Synerty utility classes for serving a static site with twisted.web with user permissions."
10
- keywords = [
11
- "twisted",
12
- "resource",
13
- "file",
14
- "download",
15
- "synerty",
16
- ]
17
- classifiers = ["Programming Language :: Python :: 3.9"]
18
- dependencies = [
19
- "pytz",
20
- "txwebsocket>=1.0.1",
21
- "filetype",
22
- "pem",
23
- "pytmpdir",
24
- "treelib>=1.6.4",
25
- "cryptography",
26
- "pyOpenSSL",
27
- ]
28
-
29
- [project.urls]
30
- Homepage = "https://github.com/Synerty/txhttputil"
31
- Download = "https://github.com/Synerty/txhttputil/tarball/1.2.11"
32
-
33
- [tool.setuptools]
34
- packages = [
35
- "txhttputil",
36
- "txhttputil.downloader",
37
- "txhttputil.login_page",
38
- "txhttputil.site",
39
- "txhttputil.util",
40
- ]
41
- include-package-data = false
@@ -1,7 +0,0 @@
1
- [metadata]
2
- description-file = README.md
3
-
4
- [egg_info]
5
- tag_build =
6
- tag_date = 0
7
-
@@ -1,3 +0,0 @@
1
-
2
-
3
- __version__ = '1.3.0'
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: txhttputil
3
- Version: 1.3.0
4
- Summary: Synerty utility classes for serving a static site with twisted.web with user permissions.
5
- Author-email: Synerty <contact@synerty.com>
6
- Project-URL: Homepage, https://github.com/Synerty/txhttputil
7
- Project-URL: Download, https://github.com/Synerty/txhttputil/tarball/1.2.11
8
- Keywords: twisted,resource,file,download,synerty
9
- Classifier: Programming Language :: Python :: 3.9
10
- License-File: LICENSE
11
- Requires-Dist: pytz
12
- Requires-Dist: txwebsocket>=1.0.1
13
- Requires-Dist: filetype
14
- Requires-Dist: pem
15
- Requires-Dist: pytmpdir
16
- Requires-Dist: treelib>=1.6.4
17
- Requires-Dist: cryptography
18
- Requires-Dist: pyOpenSSL
File without changes
File without changes
@@ -6,11 +6,11 @@
6
6
  * Website : http://www.synerty.com
7
7
  * Support : support@synerty.com
8
8
  """
9
+
9
10
  import logging
10
11
  import os
11
12
  from urllib.parse import parse_qs
12
13
 
13
-
14
14
  from pytmpdir.spooled_named_temporary_file import (
15
15
  SpooledNamedTemporaryFile,
16
16
  )