Browse Source

updated code to latest cookiecutter

main
Holger Frey 3 years ago
parent
commit
3a3e926d6f
  1. 2
      .flake8
  2. 4
      Makefile
  3. 120
      honeypot/__init__.py
  4. 24
      honeypot/utils.py
  5. 61
      pyproject.toml
  6. 8
      tests/test_honeypot.py

2
.flake8

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
[flake8]
per-file-ignores = tests/*:S101

4
Makefile

@ -76,7 +76,7 @@ install: ## install updated project.toml with flint @@ -76,7 +76,7 @@ install: ## install updated project.toml with flint
devenv: ## setup development environment
python3 -m venv --prompt honeypot .venv
.venv/bin/pip3 install --upgrade pip
.venv/bin/pip3 install flit
.venv/bin/pip3 install "flit>3.2"
.venv/bin/flit install --pth-file
repo: devenv ## complete project setup with development environment and git repo
@ -86,5 +86,5 @@ repo: devenv ## complete project setup with development environment and git repo @@ -86,5 +86,5 @@ repo: devenv ## complete project setup with development environment and git repo
git commit -m "import of project template"
git remote add origin https://git.cpi.imtek.uni-freiburg.de/CPI/honeypot.git
git push -u origin main --no-verify
.venv/bin/pre-commit install --install-hooks

120
honeypot/__init__.py

@ -6,93 +6,88 @@ A honeypot for wiki scrapers @@ -6,93 +6,88 @@ A honeypot for wiki scrapers
__version__ = "0.0.1"
import os
import pickle
import re
import pickle # noqa: S403
from collections import OrderedDict
from pyramid.httpexceptions import HTTPFound
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from pyramid_mailer.message import Message
from . import utils
class RootResource:
''' A simple 'catch all' resource '''
"""A simple 'catch all' resource"""
moin_config_dir = None
moin_wiki_defs = []
admin_emails = []
def __init__(self, request):
''' initialization '''
"""initialization"""
self.request = request
def __getitem__(self, key):
''' no child resource lookup, only one view used'''
"""no child resource lookup, only one view used"""
return self
@classmethod
def configure(cls, settings):
''' parses the moinmoin farmconfig file '''
cls.moin_config_dir = settings['moin.config_path']
moin_farmconfig = os.path.join(cls.moin_config_dir, 'farmconfig.py')
"""parses the moinmoin farmconfig file"""
cls.moin_config_dir = settings["moin.config_path"]
moin_farmconfig = os.path.join(cls.moin_config_dir, "farmconfig.py")
encoding = utils.guess_encoding(moin_farmconfig)
with open(moin_farmconfig, 'r', encoding=encoding) as fh:
with open(moin_farmconfig, "r", encoding=encoding) as fh:
cls.moin_wiki_defs = list(utils.extract_wiki_definitions(fh))
cls.admin_emails = settings['mail.admin_email'].split()
cls.admin_emails = settings["mail.admin_email"].split()
def get_moin_user(self):
''' returns a name and email address of the current wiki user'''
name, email = '<unknown user>', '<unknown email>'
"""returns a name and email address of the current wiki user"""
name, email = "<unknown user>", "<unknown email>"
try:
moin_data_dir = self._get_wiki_data_dir()
moin_session_dir = os.path.join(
moin_data_dir,
'cache',
'__session__'
)
moin_data_dir, "cache", "__session__"
)
moin_user_id = self._get_user_id(moin_session_dir)
moin_user_file = os.path.join(moin_data_dir, 'user', moin_user_id)
with open(moin_user_file, 'r') as fh:
for line in fh:
if line.startswith('email='):
email = line.split('=', 1)[1].strip()
if line.startswith('name='):
name = line.split('=', 1)[1].strip()
except:
moin_user_file = os.path.join(moin_data_dir, "user", moin_user_id)
with open(moin_user_file, "r") as fh:
for line in fh:
if line.startswith("email="):
email = line.split("=", 1)[1].strip()
if line.startswith("name="):
name = line.split("=", 1)[1].strip()
except: # noqa: S110, E722
pass
return name, email
def _get_wiki_data_dir(self):
''' get the data directory by parsing a wiki config '''
"""get the data directory by parsing a wiki config"""
wiki_name = self._get_wiki_name()
wiki_config = os.path.join(self.moin_config_dir, wiki_name + '.py')
wiki_config = os.path.join(self.moin_config_dir, wiki_name + ".py")
encoding = utils.guess_encoding(wiki_config)
with open(wiki_config, 'r', encoding=encoding) as fh:
with open(wiki_config, "r", encoding=encoding) as fh:
data_dir = utils.extract_data_dir(fh)
return data_dir
def _get_wiki_name(self):
''' return the internal wiki name for a url '''
"""return the internal wiki name for a url"""
for name, re_url in self.moin_wiki_defs:
if re.match(re_url, self.request.url):
return name
def _get_user_id(self, session_dir):
''' extract the user id from the session store '''
"""extract the user id from the session store"""
session_path = self._get_session_path(session_dir)
with open(session_path, 'rb') as fh:
session_data = pickle.load(fh)
return session_data.get('user.id')
with open(session_path, "rb") as fh:
session_data = pickle.load(fh) # noqa: S301
return session_data.get("user.id")
def _get_session_path(self, session_dir):
''' get the path to the session store for a given cookie '''
"""get the path to the session store for a given cookie"""
for key, value in self.request.cookies.items():
if key.lower().startswith('moin'):
if key.lower().startswith("moin"):
session_path = os.path.join(session_dir, value)
if os.path.isfile(session_path):
return session_path
@ -101,45 +96,44 @@ class RootResource: @@ -101,45 +96,44 @@ class RootResource:
@view_config(context=RootResource)
def the_view(context, request):
''' the one and only view for the app '''
"""the one and only view for the app"""
name, email = context.get_moin_user()
body = [
'The Honey Pot Was Accessed',
'--------------------------',
'',
'This might be an attempt to scrape the whole wiki',
'',
'wiki user: %s (%s)' % (name, email),
'',
'requested url: %s' % request.url,
'request method: %s' % request.method,
'client ip address: %s' % request.client_addr,
'remote ip address: %s' % request.remote_addr,
'',
'headers:'
]
headers = [' %s: %s' % (k, v) for k, v in request.headers.items()]
"The Honey Pot Was Accessed",
"--------------------------",
"",
"This might be an attempt to scrape the whole wiki",
"",
"wiki user: %s (%s)" % (name, email),
"",
"requested url: %s" % request.url,
"request method: %s" % request.method,
"client ip address: %s" % request.client_addr,
"remote ip address: %s" % request.remote_addr,
"",
"headers:",
]
headers = [" %s: %s" % (k, v) for k, v in request.headers.items()]
body.extend(headers)
body = '\n'.join(body)
body = "\n".join(body)
message = Message(
subject='[cpi wikis]: HoneyPot Link Was Accessed',
sender=request.registry.settings['mail.default_sender'],
subject="[cpi wikis]: HoneyPot Link Was Accessed",
sender=request.registry.settings["mail.default_sender"],
recipients=context.admin_emails,
body=body
)
body=body,
)
request.mailer.send_immediately(message)
return HTTPFound('https://www.cpi.uni-freiburg.de/')
return HTTPFound("https://www.cpi.uni-freiburg.de/")
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
"""This function returns a Pyramid WSGI application."""
RootResource.configure(settings)
config = Configurator(settings=settings)

24
honeypot/utils.py

@ -2,23 +2,24 @@ from chardet.universaldetector import UniversalDetector @@ -2,23 +2,24 @@ from chardet.universaldetector import UniversalDetector
def guess_encoding(path):
''' guess the encoding of a file at a given path '''
"""guess the encoding of a file at a given path"""
detector = UniversalDetector()
with open(path, 'rb') as fh:
with open(path, "rb") as fh:
for line in fh:
detector.feed(line)
if detector.done: break
if detector.done:
break
detector.close()
return detector.result['encoding']
return detector.result["encoding"]
def extract_wiki_definitions(file_handle):
''' extract the wiki definitions from a moinmoin farmconfig file '''
"""extract the wiki definitions from a moinmoin farmconfig file"""
for line in file_handle:
if line.startswith('wikis = ['):
if line.startswith("wikis = ["):
break
for line in file_handle:
if line.startswith(']'):
if line.startswith("]"):
break
parts = split_wiki_definitions(line)
if parts is not None:
@ -26,7 +27,7 @@ def extract_wiki_definitions(file_handle): @@ -26,7 +27,7 @@ def extract_wiki_definitions(file_handle):
def split_wiki_definitions(line):
''' small helper, returns the wiki name and wiki url regex '''
"""small helper, returns the wiki name and wiki url regex"""
for quote in ('"', "'"):
parts = line.split(quote)
if len(parts) == 5:
@ -35,12 +36,11 @@ def split_wiki_definitions(line): @@ -35,12 +36,11 @@ def split_wiki_definitions(line):
def extract_data_dir(fh):
''' returns the data directory from a single moinmoin wiki config '''
"""returns the data directory from a single moinmoin wiki config"""
for line in fh:
parts = line.split('=', 1)
parts = line.split("=", 1)
if len(parts) == 2:
name, value = parts
if name.strip() == 'data_dir':
if name.strip() == "data_dir":
value = value.strip()
return value[1:-1]

61
pyproject.toml

@ -4,14 +4,17 @@ @@ -4,14 +4,17 @@
requires = ["flit"]
build-backend = "flit.buildapi"
[tool.flit.metadata]
module = "honeypot"
dist-name = "honeypot"
author = "Holger Frey"
author-email = "frey@imtek.de"
home-page = "https://git.cpi.imtek.uni-freiburg.de/CPI/honeypot.git"
description-file = "README.md"
license = "Beerware"
[project]
name = "honeypot"
readme = "README.md"
description = "A honeypot for wiki scrapers"
license = { file = "LICENSE" }
requires-python = ">=3.7"
dynamic = ["version"]
authors = [
{name = "Holger Frey", email = "frey@imtek.de"},
]
# see https://pypi.org/classifiers/
classifiers = [
@ -26,16 +29,18 @@ classifiers = [ @@ -26,16 +29,18 @@ classifiers = [
"License :: Freely Distributable",
]
requires = [
dependencies = [
"chardet",
"plaster_pastedeploy",
"pyramid",
"pyramid_mailer",
"waitress",
]
requires-python = ">=3.7"
[tool.flit.metadata.requires-extra]
[project.urls]
Source = "https://git.cpi.imtek.uni-freiburg.de/CPI/honeypot.git"
[project.optional-dependencies]
test = [
"pytest >=4.0.0",
"pytest-cov",
@ -53,19 +58,8 @@ dev = [ @@ -53,19 +58,8 @@ dev = [
"pre-commit",
]
[tool.black]
line-length = 79
py37 = true
include = "\.pyi?$"
exclude = """
/(
\.git
| \.tox
| \.venv
| build
| dist
)/
"""
[project.entry-points."paste.app_factory"]
main = "honeypot:main"
[tool.isort]
line_length=79
@ -73,13 +67,26 @@ multi_line_output=3 @@ -73,13 +67,26 @@ multi_line_output=3
length_sort="True"
include_trailing_comma="True"
[tool.pytest.ini_options]
markers = [
'fun: marks tests as functional (deselect with "-m \"not fun\"")',
"fun: marks tests as functional (deselect with '-m \"not fun\"')",
]
addopts = [
"--strict-markers",
]
[project.entry-points."paste.app_factory"]
main = "honeypot:main"
[tool.black]
line-length = 79
target-version = ['py37','py38', 'py39']
include = '\.pyi?$'
extend-exclude = '''
# A regex preceded with ^/ will apply only to files and directories
# in the root of the project.
^/.git
^/.tox
^/.venv
^/.build
^/.dist
'''

8
tests/test_honeypot.py

@ -25,17 +25,21 @@ import pytest @@ -25,17 +25,21 @@ import pytest
def test_example_unittest():
""" example unittest
"""example unittest
will be run by 'make test' and 'make testall' but not 'make coverage'
"""
import honeypot # noqa: F401
assert True
@pytest.mark.fun
def test_example_functional_test():
""" example unittest
"""example unittest
will be by 'make coverage' and 'make testall' but not 'make test'
"""
import honeypot # noqa: F401
assert True

Loading…
Cancel
Save