viewo-api 1.0.0__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.
- viewo_api-1.0.0/LICENSE +21 -0
- viewo_api-1.0.0/PKG-INFO +25 -0
- viewo_api-1.0.0/README +1 -0
- viewo_api-1.0.0/pyproject.toml +89 -0
- viewo_api-1.0.0/setup.cfg +4 -0
- viewo_api-1.0.0/tests/test_login.py +58 -0
- viewo_api-1.0.0/tests/test_visitor.py +18 -0
- viewo_api-1.0.0/viewo_api/__init__.py +46 -0
- viewo_api-1.0.0/viewo_api/config.py +49 -0
- viewo_api-1.0.0/viewo_api/mail/__init__.py +8 -0
- viewo_api-1.0.0/viewo_api/mail/app.py +33 -0
- viewo_api-1.0.0/viewo_api/mail/send.py +37 -0
- viewo_api-1.0.0/viewo_api/mail/tech.py +42 -0
- viewo_api-1.0.0/viewo_api/mail/user.py +19 -0
- viewo_api-1.0.0/viewo_api/message.py +48 -0
- viewo_api-1.0.0/viewo_api/user/__init__.py +14 -0
- viewo_api-1.0.0/viewo_api/user/config.py +18 -0
- viewo_api-1.0.0/viewo_api/user/create.py +31 -0
- viewo_api-1.0.0/viewo_api/user/data.py +129 -0
- viewo_api-1.0.0/viewo_api/user/password.py +101 -0
- viewo_api-1.0.0/viewo_api/user/serialize.py +51 -0
- viewo_api-1.0.0/viewo_api/user/state.py +30 -0
- viewo_api-1.0.0/viewo_api/user/token.py +10 -0
- viewo_api-1.0.0/viewo_api/user/update.py +49 -0
- viewo_api-1.0.0/viewo_api/utils.py +14 -0
- viewo_api-1.0.0/viewo_api/visitor.py +68 -0
- viewo_api-1.0.0/viewo_api.egg-info/PKG-INFO +25 -0
- viewo_api-1.0.0/viewo_api.egg-info/SOURCES.txt +30 -0
- viewo_api-1.0.0/viewo_api.egg-info/dependency_links.txt +1 -0
- viewo_api-1.0.0/viewo_api.egg-info/entry_points.txt +2 -0
- viewo_api-1.0.0/viewo_api.egg-info/requires.txt +10 -0
- viewo_api-1.0.0/viewo_api.egg-info/top_level.txt +1 -0
viewo_api-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Helmut Konrad Schewe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
viewo_api-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: viewo_api
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/anaticulae/viewo_api
|
|
7
|
+
Project-URL: Repository, https://github.com/anaticulae/viewo_api
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: flask<4.0.0,>=3.1.3
|
|
15
|
+
Requires-Dist: flask-login<1.0.0,>=0.6.3
|
|
16
|
+
Requires-Dist: flask-mail<1.0.0,>=0.10.0
|
|
17
|
+
Requires-Dist: utilo<3.0.0,>=2.112.1
|
|
18
|
+
Requires-Dist: configos<2.0.0,>=1.0.4
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: utilotest<2.0.0,>=1.1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-localserver<2.0.0,>=0.10.0; extra == "dev"
|
|
22
|
+
Requires-Dist: aiosmtpd==1.4.6; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# viewo_api
|
viewo_api-1.0.0/README
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# viewo_api
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "viewo_api"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = ""
|
|
5
|
+
requires-python = ">=3.12"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Helmut Konrad Schewe", email = "helmutus@outlook.com" },
|
|
8
|
+
]
|
|
9
|
+
dependencies = [
|
|
10
|
+
"flask>=3.1.3,<4.0.0",
|
|
11
|
+
"flask-login>=0.6.3,<1.0.0",
|
|
12
|
+
"flask-mail>=0.10.0,<1.0.0",
|
|
13
|
+
"utilo>=2.112.1,<3.0.0",
|
|
14
|
+
"configos>=1.0.4,<2.0.0",
|
|
15
|
+
]
|
|
16
|
+
keywords = []
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
]
|
|
22
|
+
license = "MIT"
|
|
23
|
+
license-files = [
|
|
24
|
+
"LICENSE",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.readme]
|
|
28
|
+
file = "README"
|
|
29
|
+
content-type = "text/markdown"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"utilotest>=1.1.1,<2.0.0",
|
|
34
|
+
"pytest-localserver>=0.10.0,<2.0.0",
|
|
35
|
+
"aiosmtpd==1.4.6",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://github.com/anaticulae/viewo_api"
|
|
40
|
+
Repository = "https://github.com/anaticulae/viewo_api"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
viewo_api = "viewo_api.cli:main"
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = [
|
|
47
|
+
"setuptools>=82.0.1",
|
|
48
|
+
"wheel>=0.46.3",
|
|
49
|
+
]
|
|
50
|
+
build-backend = "setuptools.build_meta"
|
|
51
|
+
|
|
52
|
+
[tool.semantic_release]
|
|
53
|
+
version_toml = [
|
|
54
|
+
"pyproject.toml:project.version",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.semantic_release.changelog]
|
|
58
|
+
mode = "init"
|
|
59
|
+
output_format = "md"
|
|
60
|
+
|
|
61
|
+
[tool.semantic_release.changelog.default_templates]
|
|
62
|
+
changelog_file = "CHANGELOG"
|
|
63
|
+
|
|
64
|
+
[tool.semantic_release.commit_parser_options]
|
|
65
|
+
patch_tags = [
|
|
66
|
+
"fix",
|
|
67
|
+
"perf",
|
|
68
|
+
"build",
|
|
69
|
+
"chore",
|
|
70
|
+
"ci",
|
|
71
|
+
"docs",
|
|
72
|
+
"style",
|
|
73
|
+
"refactor",
|
|
74
|
+
"test",
|
|
75
|
+
"deps",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.setuptools.packages.find]
|
|
79
|
+
where = [
|
|
80
|
+
".",
|
|
81
|
+
]
|
|
82
|
+
include = [
|
|
83
|
+
"viewo_api",
|
|
84
|
+
"viewo_api.mail",
|
|
85
|
+
"viewo_api.user",
|
|
86
|
+
]
|
|
87
|
+
exclude = [
|
|
88
|
+
"tests/*",
|
|
89
|
+
]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import http
|
|
11
|
+
|
|
12
|
+
import utilotest
|
|
13
|
+
|
|
14
|
+
import viewo_api
|
|
15
|
+
import viewo_api.user.state
|
|
16
|
+
|
|
17
|
+
PASSWORD = 'helmut1337' # nosec
|
|
18
|
+
MAIL = 'modern@modern.com'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_login_logout(client): # pylint:disable=W0613
|
|
22
|
+
user = viewo_api.create_user(password=PASSWORD)
|
|
23
|
+
utilotest.apipost(
|
|
24
|
+
client,
|
|
25
|
+
'/login',
|
|
26
|
+
data={
|
|
27
|
+
'user': user.userid,
|
|
28
|
+
'password': PASSWORD,
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
utilotest.apicall(client, '/logout')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_login_wrong_password(client): # pylint:disable=W0613
|
|
35
|
+
user = viewo_api.create_user(password=PASSWORD)
|
|
36
|
+
utilotest.apipost(
|
|
37
|
+
client,
|
|
38
|
+
'/login',
|
|
39
|
+
data={
|
|
40
|
+
'user': user.userid,
|
|
41
|
+
'password': 'wrong'
|
|
42
|
+
}, # nosec
|
|
43
|
+
expected=http.HTTPStatus.FORBIDDEN,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_login_withmail(client): # pylint:disable=W0613
|
|
48
|
+
user = viewo_api.create_user(password=PASSWORD)
|
|
49
|
+
assert viewo_api.user_email_update(email=MAIL, userid=user.userid)
|
|
50
|
+
utilotest.apipost(
|
|
51
|
+
client,
|
|
52
|
+
'/login',
|
|
53
|
+
data={
|
|
54
|
+
'user': MAIL,
|
|
55
|
+
'password': PASSWORD,
|
|
56
|
+
},
|
|
57
|
+
)
|
|
58
|
+
utilotest.apicall(client, '/logout')
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import utilotest
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_request(client): # pylint:disable=W0621
|
|
14
|
+
response = utilotest.decode(client.get('/return_request'))
|
|
15
|
+
assert 'Env(hashed=' in response
|
|
16
|
+
# assert "agent='Werkzeug/3.1.8', method='GET', path='/return_request'" in response
|
|
17
|
+
assert "agent='Werkzeug/" in response
|
|
18
|
+
assert "', method='GET', path='/return_request'" in response
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
#------------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
#==============================================================================
|
|
9
|
+
|
|
10
|
+
import importlib.metadata
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
from viewo_api.mail.send import send_mail
|
|
14
|
+
from viewo_api.mail.tech import send_upload_info
|
|
15
|
+
from viewo_api.message import bad
|
|
16
|
+
from viewo_api.message import internal
|
|
17
|
+
from viewo_api.message import notfound
|
|
18
|
+
from viewo_api.message import success
|
|
19
|
+
from viewo_api.user.config import userspath
|
|
20
|
+
from viewo_api.user.create import create_user
|
|
21
|
+
from viewo_api.user.data import FlaskUser
|
|
22
|
+
from viewo_api.user.data import User
|
|
23
|
+
from viewo_api.user.data import hash_email
|
|
24
|
+
from viewo_api.user.data import user_fromid
|
|
25
|
+
from viewo_api.user.data import userlist_raw
|
|
26
|
+
from viewo_api.user.data import userpublic_fromid
|
|
27
|
+
from viewo_api.user.password import password_generate
|
|
28
|
+
from viewo_api.user.password import password_public_set
|
|
29
|
+
from viewo_api.user.password import password_valid
|
|
30
|
+
from viewo_api.user.password import password_verify
|
|
31
|
+
from viewo_api.user.password import username_valid
|
|
32
|
+
from viewo_api.user.state import login
|
|
33
|
+
from viewo_api.user.state import logout
|
|
34
|
+
from viewo_api.user.update import user_append_document
|
|
35
|
+
from viewo_api.user.update import user_email_update
|
|
36
|
+
from viewo_api.user.update import user_update
|
|
37
|
+
from viewo_api.utils import json
|
|
38
|
+
from viewo_api.visitor import access
|
|
39
|
+
from viewo_api.visitor import oneline
|
|
40
|
+
from viewo_api.visitor import request
|
|
41
|
+
from viewo_api.visitor import user_current
|
|
42
|
+
from viewo_api.visitor import user_hash
|
|
43
|
+
|
|
44
|
+
__version__ = importlib.metadata.version('viewo_api')
|
|
45
|
+
|
|
46
|
+
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import configos
|
|
11
|
+
import flask
|
|
12
|
+
|
|
13
|
+
PASSWORD_SALT = configos.HV_STR(default='THISISSALT')
|
|
14
|
+
|
|
15
|
+
PASSWORD_DIGITS = configos.HV_INT_PLUS(default=64)
|
|
16
|
+
|
|
17
|
+
PASSWORD_RANDOM_LENGTH = configos.HV_INT_PLUS(default=16)
|
|
18
|
+
|
|
19
|
+
PASSWORD_MIN_LENGTH = configos.HV_INT_PLUS(default=8)
|
|
20
|
+
PASSWORD_MAX_LENGTH = configos.HV_INT_PLUS(default=64)
|
|
21
|
+
|
|
22
|
+
USER_LENGTH = configos.HV_INT_PLUS(default=16)
|
|
23
|
+
|
|
24
|
+
EMAIL_SALT = configos.HV_STR(default='EMAILNOGMAIL')
|
|
25
|
+
|
|
26
|
+
EMAIL_DIGITS = configos.HV_INT_PLUS(default=64)
|
|
27
|
+
|
|
28
|
+
EMAIL_NO_AUTHOR = configos.HV_STR(default='postkasten@checkitweg.de')
|
|
29
|
+
|
|
30
|
+
EMAIL_SERVER = configos.HV_STR(default='guardian@checkitweg.de')
|
|
31
|
+
# inform admin about new customer
|
|
32
|
+
EMAIL_CUSTOMER_NEW = configos.env('CHANIA_CUSTOMER_NEW', default=None)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def common():
|
|
36
|
+
return flask.current_app.config['COMMON']
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def todo():
|
|
40
|
+
return flask.current_app.config['TODO']
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def ready():
|
|
44
|
+
return flask.current_app.config['READY']
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
configos.todo = todo
|
|
48
|
+
configos.ready = ready
|
|
49
|
+
configos.share = common
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask
|
|
11
|
+
import flask_mail
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def register(app):
|
|
15
|
+
mail = flask_mail.Mail(app)
|
|
16
|
+
app.mail = mail
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def configure(
|
|
20
|
+
server,
|
|
21
|
+
user=None,
|
|
22
|
+
password=None,
|
|
23
|
+
tls: bool = False,
|
|
24
|
+
port: int = 587,
|
|
25
|
+
):
|
|
26
|
+
config = flask.current_app.config
|
|
27
|
+
config['MAIL_SERVER'] = server
|
|
28
|
+
config['MAIL_PORT'] = port
|
|
29
|
+
config['MAIL_USERNAME'] = user
|
|
30
|
+
config['MAIL_PASSWORD'] = password
|
|
31
|
+
config['MAIL_USE_TLS'] = tls
|
|
32
|
+
config['MAIL_SUPPRESS_SEND'] = False
|
|
33
|
+
flask.current_app.mail.init_app(flask.current_app)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask
|
|
11
|
+
import flask_mail
|
|
12
|
+
|
|
13
|
+
import viewo_api.config
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def send_mail(
|
|
17
|
+
recipient: str,
|
|
18
|
+
subject: str,
|
|
19
|
+
body: str,
|
|
20
|
+
author: str = viewo_api.config.EMAIL_NO_AUTHOR,
|
|
21
|
+
):
|
|
22
|
+
msg = flask_mail.Message(
|
|
23
|
+
recipients=[recipient],
|
|
24
|
+
subject=subject,
|
|
25
|
+
body=body,
|
|
26
|
+
sender=author.value,
|
|
27
|
+
)
|
|
28
|
+
flask.current_app.mail.send(msg)
|
|
29
|
+
# threading.Thread(
|
|
30
|
+
# target=send_async,
|
|
31
|
+
# args=[flask.current_app, msg],
|
|
32
|
+
# ).start()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# def send_async( msg):
|
|
36
|
+
# with app.app_context():
|
|
37
|
+
# app.mail.send(msg)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import utilo
|
|
11
|
+
|
|
12
|
+
import viewo_api
|
|
13
|
+
import viewo_api.config
|
|
14
|
+
|
|
15
|
+
MESSAGE_NEW_SUBJECT = 'New Customer'
|
|
16
|
+
MESSAGE_NEW_BODY = """\
|
|
17
|
+
New customer on the line!
|
|
18
|
+
|
|
19
|
+
{data}
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def send_upload_info(data: dict = None):
|
|
24
|
+
if viewo_api.config.EMAIL_CUSTOMER_NEW is None:
|
|
25
|
+
msg = 'CONFIGURE: CHANIA_CUSTOMER_NEW could not send_upload_info'
|
|
26
|
+
utilo.error(msg)
|
|
27
|
+
return
|
|
28
|
+
data = utilo.dict_dump(data) if data else ''
|
|
29
|
+
body = MESSAGE_NEW_BODY.format(data=data)
|
|
30
|
+
viewo_api.send_mail(
|
|
31
|
+
recipient=viewo_api.config.EMAIL_CUSTOMER_NEW,
|
|
32
|
+
subject=MESSAGE_NEW_SUBJECT,
|
|
33
|
+
body=body,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def send_server_status():
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def send_login_request():
|
|
42
|
+
"""Send token before login into admin area."""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
# import viewo_api.mail.send
|
|
11
|
+
|
|
12
|
+
# TEMPLATE = """\
|
|
13
|
+
# Änderung erfordert Bestätigung
|
|
14
|
+
|
|
15
|
+
# """
|
|
16
|
+
|
|
17
|
+
# def verify_change(email: str, token: str, title: str, message: str):
|
|
18
|
+
# """Send E-Mail to user to verify user action."""
|
|
19
|
+
# # viewo_api.email.send.email()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask
|
|
11
|
+
|
|
12
|
+
import viewo_api
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def success(message: str = 'completed', **args):
|
|
16
|
+
result = viewo_api.json({
|
|
17
|
+
'message': message,
|
|
18
|
+
**args,
|
|
19
|
+
})
|
|
20
|
+
return result, 200
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def notfound(message: str):
|
|
24
|
+
result = viewo_api.json({
|
|
25
|
+
'error': 'not found',
|
|
26
|
+
'message': message,
|
|
27
|
+
})
|
|
28
|
+
return result, 404
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def bad(message: str):
|
|
32
|
+
result = viewo_api.json({
|
|
33
|
+
'error': 'bad request',
|
|
34
|
+
'message': message,
|
|
35
|
+
})
|
|
36
|
+
return result, 400
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def internal(message: str):
|
|
40
|
+
result = viewo_api.json({
|
|
41
|
+
'error': 'internal',
|
|
42
|
+
'message': message,
|
|
43
|
+
})
|
|
44
|
+
return result, 500
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def flash(message: str):
|
|
48
|
+
flask.flash(message)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
"""Users
|
|
10
|
+
=====
|
|
11
|
+
|
|
12
|
+
* public user: open browser and view page
|
|
13
|
+
* private user: account which is logged in via login form
|
|
14
|
+
"""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
import viewo_api.config
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def userspath():
|
|
16
|
+
result = os.path.join(viewo_api.config.common(), 'users')
|
|
17
|
+
os.makedirs(result, exist_ok=True)
|
|
18
|
+
return result
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
import utilo
|
|
13
|
+
|
|
14
|
+
import viewo_api.config
|
|
15
|
+
import viewo_api.user.data
|
|
16
|
+
import viewo_api.user.password
|
|
17
|
+
import viewo_api.user.update
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def create_user(password: str, userid: str = None):
|
|
21
|
+
# validate password
|
|
22
|
+
password = viewo_api.user.password.hashed(password)
|
|
23
|
+
# generate new random user name
|
|
24
|
+
if not userid:
|
|
25
|
+
userid = utilo.tmpname(viewo_api.config.USER_LENGTH)
|
|
26
|
+
while os.path.exists(viewo_api.user.data.userpath(userid, False)):
|
|
27
|
+
userid = utilo.tmpname(viewo_api.config.USER_LENGTH)
|
|
28
|
+
new = viewo_api.user.data.User(userid=userid, password=password)
|
|
29
|
+
# write to user database
|
|
30
|
+
viewo_api.user.update.user_update(new)
|
|
31
|
+
return new
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import dataclasses
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
import flask_login
|
|
14
|
+
import utilo
|
|
15
|
+
|
|
16
|
+
import viewo_api.user.config
|
|
17
|
+
import viewo_api.user.password
|
|
18
|
+
import viewo_api.user.serialize
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclasses.dataclass(unsafe_hash=True)
|
|
22
|
+
class User:
|
|
23
|
+
email: str = None
|
|
24
|
+
password: str = None
|
|
25
|
+
documents: list = dataclasses.field(default_factory=list)
|
|
26
|
+
payed: int = None
|
|
27
|
+
userid: str = None
|
|
28
|
+
|
|
29
|
+
def append_document(self, documentid: str):
|
|
30
|
+
assert documentid not in self.documents # pylint:disable=E1135
|
|
31
|
+
self.documents.append(documentid) # pylint:disable=E1101
|
|
32
|
+
|
|
33
|
+
def __getitem__(self, index):
|
|
34
|
+
return self.documents[index] # pylint:disable=E1136
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
Users = list[User]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def user_fromid(userid: str) -> User:
|
|
41
|
+
path = userpath(userid, verify=True)
|
|
42
|
+
if not path:
|
|
43
|
+
# try to find user via email
|
|
44
|
+
user = user_from_email(userid)
|
|
45
|
+
return user
|
|
46
|
+
if not path:
|
|
47
|
+
return None
|
|
48
|
+
loaded = viewo_api.user.serialize.load_user(path)
|
|
49
|
+
return loaded
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def user_from_email(email: str) -> User:
|
|
53
|
+
email = hash_email(email)
|
|
54
|
+
for user in users():
|
|
55
|
+
if user.email != email:
|
|
56
|
+
continue
|
|
57
|
+
return user
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def userpath(userid: int, verify: bool = False) -> str:
|
|
62
|
+
result = os.path.join(viewo_api.user.config.userspath(), userid)
|
|
63
|
+
if verify and not os.path.exists(result):
|
|
64
|
+
return None
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def users():
|
|
69
|
+
upath = viewo_api.user.config.userspath()
|
|
70
|
+
common_user = viewo_api.user.serialize.load_users(upath)
|
|
71
|
+
return common_user
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def userlist_raw():
|
|
75
|
+
upath = viewo_api.user.config.userspath()
|
|
76
|
+
common_user = viewo_api.user.serialize.load_users(upath)
|
|
77
|
+
raw = [viewo_api.user.serialize.user_raw(item) for item in common_user]
|
|
78
|
+
return raw
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def userpublic_fromid(userid: str) -> dict:
|
|
82
|
+
"""Returns public data which are not security/data privacy
|
|
83
|
+
relevant."""
|
|
84
|
+
user = user_fromid(userid)
|
|
85
|
+
if not user:
|
|
86
|
+
return None
|
|
87
|
+
result = {
|
|
88
|
+
'user': userid,
|
|
89
|
+
'documents': list(user.documents),
|
|
90
|
+
}
|
|
91
|
+
if user.email:
|
|
92
|
+
# TODO: IS THIS A GOOD IDEA?
|
|
93
|
+
# TODO: VERIFY BEFORE RELEASE XXX
|
|
94
|
+
result['email'] = user.email
|
|
95
|
+
if user.payed is not None:
|
|
96
|
+
result['payed'] = user.payed
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def hash_email(email: str):
|
|
101
|
+
"""\
|
|
102
|
+
>>> hash_email('toy@roy.com')
|
|
103
|
+
'...'
|
|
104
|
+
"""
|
|
105
|
+
email = utilo.secure_hash(
|
|
106
|
+
email,
|
|
107
|
+
salt=viewo_api.config.EMAIL_SALT,
|
|
108
|
+
digits=viewo_api.config.EMAIL_DIGITS,
|
|
109
|
+
)
|
|
110
|
+
return email
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclasses.dataclass
|
|
114
|
+
class FlaskUser(flask_login.UserMixin):
|
|
115
|
+
identifier: str = None
|
|
116
|
+
|
|
117
|
+
def get_id(self):
|
|
118
|
+
return self.identifier
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def payed(self):
|
|
122
|
+
user = user_fromid(self.identifier)
|
|
123
|
+
if not user:
|
|
124
|
+
return 0
|
|
125
|
+
return user.payed
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def is_admin(self):
|
|
129
|
+
return False
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask
|
|
11
|
+
import utilo
|
|
12
|
+
|
|
13
|
+
import viewo_api.config
|
|
14
|
+
import viewo_api.user
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PasswordError(ValueError):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PasswordTooShort(PasswordError):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PasswordTooLong(PasswordError):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def password_valid(password: str) -> bool:
|
|
30
|
+
"""\
|
|
31
|
+
>>> password_valid('short')
|
|
32
|
+
Traceback (most recent call last):
|
|
33
|
+
...
|
|
34
|
+
viewo_api.user.password.PasswordTooShort
|
|
35
|
+
|
|
36
|
+
>>> password_valid('VeryLongPassword1337')
|
|
37
|
+
True
|
|
38
|
+
"""
|
|
39
|
+
if password is None:
|
|
40
|
+
return False
|
|
41
|
+
password = str(password)
|
|
42
|
+
if len(password) < viewo_api.config.PASSWORD_MIN_LENGTH:
|
|
43
|
+
raise PasswordTooShort
|
|
44
|
+
if len(password) > viewo_api.config.PASSWORD_MAX_LENGTH:
|
|
45
|
+
raise PasswordTooLong
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def hashed(password: str) -> str:
|
|
50
|
+
"""\
|
|
51
|
+
>>> len(hashed('nononono'))
|
|
52
|
+
64
|
|
53
|
+
"""
|
|
54
|
+
password_valid(password)
|
|
55
|
+
password = utilo.secure_hash(
|
|
56
|
+
password,
|
|
57
|
+
salt=viewo_api.config.PASSWORD_SALT,
|
|
58
|
+
digits=viewo_api.config.PASSWORD_DIGITS,
|
|
59
|
+
)
|
|
60
|
+
return password
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def password_generate(length=viewo_api.config.PASSWORD_RANDOM_LENGTH) -> str:
|
|
64
|
+
"""\
|
|
65
|
+
>>> assert len(password_generate(10)) == 10
|
|
66
|
+
"""
|
|
67
|
+
random = utilo.tmpname(length)
|
|
68
|
+
return random
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def password_verify(userid: str, password: str) -> bool:
|
|
72
|
+
user = viewo_api.user.data.user_fromid(userid)
|
|
73
|
+
if not user:
|
|
74
|
+
# try to select user via email
|
|
75
|
+
user = viewo_api.user.data.user_from_email(userid)
|
|
76
|
+
if not user:
|
|
77
|
+
return False
|
|
78
|
+
try:
|
|
79
|
+
password = viewo_api.user.password.hashed(password)
|
|
80
|
+
except viewo_api.user.password.PasswordError:
|
|
81
|
+
return False
|
|
82
|
+
return password == user.password
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def password_public_set(password: str):
|
|
86
|
+
# TODO: CHECK FOR SECURITY ISSUES
|
|
87
|
+
flask.globals.session['password_raw'] = password
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def username_valid(name) -> False:
|
|
91
|
+
"""\
|
|
92
|
+
>>> username_valid('not a valid user')
|
|
93
|
+
False
|
|
94
|
+
>>> username_valid('012ABxxF012ABxxF')
|
|
95
|
+
True
|
|
96
|
+
>>> username_valid(' 12 xxx')
|
|
97
|
+
False
|
|
98
|
+
"""
|
|
99
|
+
if not len(name) == viewo_api.config.USER_LENGTH:
|
|
100
|
+
return False
|
|
101
|
+
return all(item.isalnum() for item in name)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
import utilo
|
|
13
|
+
|
|
14
|
+
import viewo_api.user.data
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def user_raw(user: 'User') -> dict:
|
|
18
|
+
result = {
|
|
19
|
+
'documents': user.documents,
|
|
20
|
+
'userid': user.userid,
|
|
21
|
+
'payed': user.payed,
|
|
22
|
+
}
|
|
23
|
+
return result
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def dump_users(users: 'Users', path: str):
|
|
27
|
+
assert os.path.exists(path), path
|
|
28
|
+
for user in users:
|
|
29
|
+
dumped = dump_user(user)
|
|
30
|
+
outpath = os.path.join(path, user.userid)
|
|
31
|
+
utilo.file_replace(outpath, dumped)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def load_users(path: str) -> 'Users':
|
|
35
|
+
assert os.path.exists(path), path
|
|
36
|
+
files = utilo.file_list(path)
|
|
37
|
+
files = utilo.files_sort(files)
|
|
38
|
+
loaded = [load_user(os.path.join(path, item)) for item in files]
|
|
39
|
+
return loaded
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def dump_user(user: 'User') -> str:
|
|
43
|
+
raw = vars(user)
|
|
44
|
+
dumped = utilo.yaml_dump(raw)
|
|
45
|
+
return dumped
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_user(path: str) -> 'User':
|
|
49
|
+
loaded = utilo.yaml_load(path)
|
|
50
|
+
result = viewo_api.user.data.User(**loaded)
|
|
51
|
+
return result
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask_login
|
|
11
|
+
|
|
12
|
+
import viewo_api.message
|
|
13
|
+
import viewo_api.user.data
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def login(userid: str, password: str, publicpassword: bool = False):
|
|
17
|
+
if not viewo_api.password_verify(userid, password):
|
|
18
|
+
return False
|
|
19
|
+
flask_login.login_user(viewo_api.FlaskUser(userid))
|
|
20
|
+
if publicpassword:
|
|
21
|
+
viewo_api.password_public_set(password)
|
|
22
|
+
viewo_api.message.flash('Login erfolgreich.')
|
|
23
|
+
return True
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def logout():
|
|
27
|
+
flask_login.logout_user()
|
|
28
|
+
# remove public password
|
|
29
|
+
viewo_api.password_public_set('')
|
|
30
|
+
viewo_api.message.flash('Logout erfolgreich.')
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
# TODO: SEE MAIL.USER
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import utilo
|
|
11
|
+
|
|
12
|
+
import viewo_api
|
|
13
|
+
import viewo_api.user.data
|
|
14
|
+
import viewo_api.user.serialize
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def user_update(user: 'User', verify=False) -> bool:
|
|
18
|
+
path = viewo_api.user.data.userpath(user.userid, verify=verify)
|
|
19
|
+
if not path:
|
|
20
|
+
return False
|
|
21
|
+
dumped = viewo_api.user.serialize.dump_user(user)
|
|
22
|
+
# TODO: NOT THREAD SAFE
|
|
23
|
+
utilo.file_replace(path, dumped)
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
PUBLIC_OWNER = '00000000'
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def user_append_document(userid: str, documentid: str) -> bool:
|
|
31
|
+
# TODO: REPLACE LATER
|
|
32
|
+
if userid == PUBLIC_OWNER:
|
|
33
|
+
# if userid == link.PUBLIC_OWNER:
|
|
34
|
+
# do not add public document to public user
|
|
35
|
+
return False
|
|
36
|
+
user = viewo_api.user.data.user_fromid(userid)
|
|
37
|
+
user.append_document(documentid)
|
|
38
|
+
user_update(user)
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def user_email_update(email: str, userid: str = None) -> bool:
|
|
43
|
+
user = viewo_api.user.data.user_fromid(userid)
|
|
44
|
+
if not user:
|
|
45
|
+
return False
|
|
46
|
+
user.email = viewo_api.hash_email(email)
|
|
47
|
+
# write to user database
|
|
48
|
+
user_update(user)
|
|
49
|
+
return True
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import flask
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def json(content) -> dict:
|
|
14
|
+
return flask.jsonify(content)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021-2022 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import collections
|
|
11
|
+
|
|
12
|
+
import flask
|
|
13
|
+
import utilo
|
|
14
|
+
|
|
15
|
+
Access = collections.namedtuple('Access', 'ip, agent')
|
|
16
|
+
Env = collections.namedtuple(
|
|
17
|
+
'Env',
|
|
18
|
+
'hashed, time, ip, agent, method, path, data, dictum',
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def request() -> Env:
|
|
23
|
+
env = flask.request.environ
|
|
24
|
+
if not env:
|
|
25
|
+
return None
|
|
26
|
+
ip = env.get('REMOTE_ADDR', 'NO_REMOTE_ADDR')
|
|
27
|
+
agent = env.get('HTTP_USER_AGENT', 'NO_HTTP_USER_AGENT')
|
|
28
|
+
hashed = user_hash(ip, agent)
|
|
29
|
+
method = env.get('REQUEST_METHOD', 'NO_USER_AGENT')
|
|
30
|
+
path = env.get('PATH_INFO', 'NO_PATH_INFO')
|
|
31
|
+
data = env.get('QUERY_STRING', 'NO_QUERY_STRING')
|
|
32
|
+
data = oneline(data)
|
|
33
|
+
time = utilo.now()
|
|
34
|
+
try:
|
|
35
|
+
dictum = flask.request.form.to_dict()
|
|
36
|
+
except OSError:
|
|
37
|
+
utilo.error(f'invalid/incomplete request: {flask.request}')
|
|
38
|
+
utilo.debug(vars(flask.request))
|
|
39
|
+
dictum = {}
|
|
40
|
+
return Env(hashed, time, ip, agent, method, path, data, dictum)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def user_hash(ip, agent) -> int:
|
|
44
|
+
return hash(f'{ip}:{agent}')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def access(env: Env):
|
|
48
|
+
return Access(env.ip, env.agent)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def user_current() -> int:
|
|
52
|
+
current = request()
|
|
53
|
+
hashed = user_hash(current.ip, current.agent)
|
|
54
|
+
return hashed
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def oneline(data, limit: int = 256):
|
|
58
|
+
r"""Remove newlines and shrink content to `limit` to avoid logging to
|
|
59
|
+
mutch data.
|
|
60
|
+
|
|
61
|
+
>>> oneline('first\nnewline')
|
|
62
|
+
'first%NL%newline'
|
|
63
|
+
"""
|
|
64
|
+
data = data.replace('\r\n', '%WNL%')
|
|
65
|
+
data = data.replace('\n', '%NL%')
|
|
66
|
+
data = data.replace(' ', '%WS%')
|
|
67
|
+
data = data[0:limit]
|
|
68
|
+
return data
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: viewo_api
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/anaticulae/viewo_api
|
|
7
|
+
Project-URL: Repository, https://github.com/anaticulae/viewo_api
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: flask<4.0.0,>=3.1.3
|
|
15
|
+
Requires-Dist: flask-login<1.0.0,>=0.6.3
|
|
16
|
+
Requires-Dist: flask-mail<1.0.0,>=0.10.0
|
|
17
|
+
Requires-Dist: utilo<3.0.0,>=2.112.1
|
|
18
|
+
Requires-Dist: configos<2.0.0,>=1.0.4
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: utilotest<2.0.0,>=1.1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-localserver<2.0.0,>=0.10.0; extra == "dev"
|
|
22
|
+
Requires-Dist: aiosmtpd==1.4.6; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# viewo_api
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README
|
|
3
|
+
pyproject.toml
|
|
4
|
+
tests/test_login.py
|
|
5
|
+
tests/test_visitor.py
|
|
6
|
+
viewo_api/__init__.py
|
|
7
|
+
viewo_api/config.py
|
|
8
|
+
viewo_api/message.py
|
|
9
|
+
viewo_api/utils.py
|
|
10
|
+
viewo_api/visitor.py
|
|
11
|
+
viewo_api.egg-info/PKG-INFO
|
|
12
|
+
viewo_api.egg-info/SOURCES.txt
|
|
13
|
+
viewo_api.egg-info/dependency_links.txt
|
|
14
|
+
viewo_api.egg-info/entry_points.txt
|
|
15
|
+
viewo_api.egg-info/requires.txt
|
|
16
|
+
viewo_api.egg-info/top_level.txt
|
|
17
|
+
viewo_api/mail/__init__.py
|
|
18
|
+
viewo_api/mail/app.py
|
|
19
|
+
viewo_api/mail/send.py
|
|
20
|
+
viewo_api/mail/tech.py
|
|
21
|
+
viewo_api/mail/user.py
|
|
22
|
+
viewo_api/user/__init__.py
|
|
23
|
+
viewo_api/user/config.py
|
|
24
|
+
viewo_api/user/create.py
|
|
25
|
+
viewo_api/user/data.py
|
|
26
|
+
viewo_api/user/password.py
|
|
27
|
+
viewo_api/user/serialize.py
|
|
28
|
+
viewo_api/user/state.py
|
|
29
|
+
viewo_api/user/token.py
|
|
30
|
+
viewo_api/user/update.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
viewo_api
|