1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
from pyramid_multiauth import MultiAuthenticationPolicy |
3
|
|
|
|
4
|
|
|
try: # Python 3.5+ |
5
|
|
|
from http import HTTPStatus |
6
|
|
|
except ImportError: |
7
|
|
|
from http import client as HTTPStatus |
8
|
|
|
|
9
|
|
|
from pyramid.config import Configurator |
10
|
|
|
from pyramid.authentication import BasicAuthAuthenticationPolicy, \ |
11
|
|
|
SessionAuthenticationPolicy |
12
|
|
|
from pyramid.authentication import AuthTktAuthenticationPolicy |
13
|
|
|
from hapic.ext.pyramid import PyramidContext |
14
|
|
|
from sqlalchemy.exc import OperationalError |
15
|
|
|
|
16
|
|
|
from tracim_backend.extensions import hapic |
17
|
|
|
from tracim_backend.config import CFG |
18
|
|
|
from tracim_backend.lib.utils.request import TracimRequest |
19
|
|
|
from tracim_backend.lib.utils.authentification import basic_auth_check_credentials |
20
|
|
|
from tracim_backend.lib.utils.authentification import CookieSessionAuthentificationPolicy |
21
|
|
|
from tracim_backend.lib.utils.authentification import ApiTokenAuthentificationPolicy |
22
|
|
|
from tracim_backend.lib.utils.authentification import TRACIM_API_KEY_HEADER |
23
|
|
|
from tracim_backend.lib.utils.authentification import TRACIM_API_USER_EMAIL_LOGIN_HEADER |
24
|
|
|
from tracim_backend.lib.utils.authentification import BASIC_AUTH_WEBUI_REALM |
25
|
|
|
from tracim_backend.lib.utils.authorization import AcceptAllAuthorizationPolicy |
26
|
|
|
from tracim_backend.lib.utils.authorization import TRACIM_DEFAULT_PERM |
27
|
|
|
from tracim_backend.lib.utils.cors import add_cors_support |
28
|
|
|
from tracim_backend.lib.webdav import WebdavAppFactory |
29
|
|
|
from tracim_backend.views import BASE_API_V2 |
30
|
|
|
from tracim_backend.views.contents_api.html_document_controller import HTMLDocumentController # nopep8 |
31
|
|
|
from tracim_backend.views.contents_api.threads_controller import ThreadController |
32
|
|
|
from tracim_backend.views.core_api.session_controller import SessionController |
33
|
|
|
from tracim_backend.views.core_api.system_controller import SystemController |
34
|
|
|
from tracim_backend.views.core_api.user_controller import UserController |
35
|
|
|
from tracim_backend.views.core_api.workspace_controller import WorkspaceController |
36
|
|
|
from tracim_backend.views.contents_api.comment_controller import CommentController |
37
|
|
|
from tracim_backend.views.contents_api.file_controller import FileController |
38
|
|
|
from tracim_backend.views.contents_api.folder_controller import FolderController |
39
|
|
|
from tracim_backend.views.frontend import FrontendController |
40
|
|
|
from tracim_backend.views.errors import ErrorSchema |
41
|
|
|
from tracim_backend.exceptions import NotAuthenticated |
42
|
|
|
from tracim_backend.exceptions import PageNotFound |
43
|
|
|
from tracim_backend.exceptions import UserNotActive |
44
|
|
|
from tracim_backend.exceptions import InvalidId |
45
|
|
|
from tracim_backend.exceptions import InsufficientUserProfile |
46
|
|
|
from tracim_backend.exceptions import InsufficientUserRoleInWorkspace |
47
|
|
|
from tracim_backend.exceptions import WorkspaceNotFoundInTracimRequest |
48
|
|
|
from tracim_backend.exceptions import UserNotFoundInTracimRequest |
49
|
|
|
from tracim_backend.exceptions import ContentNotFoundInTracimRequest |
50
|
|
|
from tracim_backend.exceptions import WorkspaceNotFound |
51
|
|
|
from tracim_backend.exceptions import ContentNotFound |
52
|
|
|
from tracim_backend.exceptions import UserDoesNotExist |
53
|
|
|
from tracim_backend.exceptions import AuthenticationFailed |
54
|
|
|
from tracim_backend.exceptions import ContentTypeNotAllowed |
55
|
|
|
|
56
|
|
|
|
57
|
|
|
def test(*args, **kwargs): |
58
|
|
|
return [] |
59
|
|
|
|
60
|
|
|
|
61
|
|
|
def web(global_config, **local_settings): |
62
|
|
|
""" This function returns a Pyramid WSGI application. |
63
|
|
|
""" |
64
|
|
|
settings = global_config |
65
|
|
|
settings.update(local_settings) |
66
|
|
|
# set CFG object |
67
|
|
|
app_config = CFG(settings) |
68
|
|
|
app_config.configure_filedepot() |
69
|
|
|
settings['CFG'] = app_config |
70
|
|
|
configurator = Configurator(settings=settings, autocommit=True) |
71
|
|
|
# Add AuthPolicy |
72
|
|
|
configurator.include("pyramid_beaker") |
73
|
|
|
configurator.include("pyramid_multiauth") |
74
|
|
|
policies = [ |
75
|
|
|
CookieSessionAuthentificationPolicy(reissue_time=app_config.SESSION_REISSUE_TIME), # nopep8 |
76
|
|
|
ApiTokenAuthentificationPolicy( |
77
|
|
|
api_key_header=TRACIM_API_KEY_HEADER, |
78
|
|
|
api_user_email_login_header=TRACIM_API_USER_EMAIL_LOGIN_HEADER |
79
|
|
|
), |
80
|
|
|
BasicAuthAuthenticationPolicy( |
81
|
|
|
basic_auth_check_credentials, |
82
|
|
|
realm=BASIC_AUTH_WEBUI_REALM |
83
|
|
|
), |
84
|
|
|
] |
85
|
|
|
configurator.include(add_cors_support) |
86
|
|
|
# make sure to add this before other routes to intercept OPTIONS |
87
|
|
|
configurator.add_cors_preflight_handler() |
88
|
|
|
# Default authorization : Accept anything. |
89
|
|
|
configurator.set_authorization_policy(AcceptAllAuthorizationPolicy()) |
90
|
|
|
authn_policy = MultiAuthenticationPolicy(policies) |
91
|
|
|
configurator.set_authentication_policy(authn_policy) |
92
|
|
|
# INFO - GM - 11-04-2018 - set default perm |
93
|
|
|
# setting default perm is needed to force authentification |
94
|
|
|
# mecanism in all views. |
95
|
|
|
configurator.set_default_permission(TRACIM_DEFAULT_PERM) |
96
|
|
|
# Override default request |
97
|
|
|
configurator.set_request_factory(TracimRequest) |
98
|
|
|
# Pyramids "plugin" include. |
99
|
|
|
configurator.include('pyramid_jinja2') |
100
|
|
|
# Add SqlAlchemy DB |
101
|
|
|
configurator.include('.models') |
102
|
|
|
# set Hapic |
103
|
|
|
context = PyramidContext( |
104
|
|
|
configurator=configurator, |
105
|
|
|
default_error_builder=ErrorSchema(), |
106
|
|
|
debug=app_config.DEBUG, |
107
|
|
|
) |
108
|
|
|
hapic.set_context(context) |
109
|
|
|
# INFO - G.M - 2018-07-04 - global-context exceptions |
110
|
|
|
# Not found |
111
|
|
|
context.handle_exception(PageNotFound, HTTPStatus.NOT_FOUND) |
112
|
|
|
# Bad request |
113
|
|
|
context.handle_exception(WorkspaceNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST) # nopep8 |
114
|
|
|
context.handle_exception(UserNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST) # nopep8 |
115
|
|
|
context.handle_exception(ContentNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST) # nopep8 |
116
|
|
|
context.handle_exception(WorkspaceNotFound, HTTPStatus.BAD_REQUEST) |
117
|
|
|
context.handle_exception(UserDoesNotExist, HTTPStatus.BAD_REQUEST) |
118
|
|
|
context.handle_exception(ContentNotFound, HTTPStatus.BAD_REQUEST) |
119
|
|
|
context.handle_exception(ContentTypeNotAllowed, HTTPStatus.BAD_REQUEST) |
120
|
|
|
context.handle_exception(InvalidId, HTTPStatus.BAD_REQUEST) |
121
|
|
|
# Auth exception |
122
|
|
|
context.handle_exception(NotAuthenticated, HTTPStatus.UNAUTHORIZED) |
123
|
|
|
context.handle_exception(UserNotActive, HTTPStatus.FORBIDDEN) |
124
|
|
|
context.handle_exception(AuthenticationFailed, HTTPStatus.FORBIDDEN) |
125
|
|
|
context.handle_exception(InsufficientUserRoleInWorkspace, HTTPStatus.FORBIDDEN) # nopep8 |
126
|
|
|
context.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN) |
127
|
|
|
# Internal server error |
128
|
|
|
context.handle_exception(OperationalError, HTTPStatus.INTERNAL_SERVER_ERROR) |
129
|
|
|
context.handle_exception(Exception, HTTPStatus.INTERNAL_SERVER_ERROR) |
130
|
|
|
|
131
|
|
|
|
132
|
|
|
# Add controllers |
133
|
|
|
session_controller = SessionController() |
134
|
|
|
system_controller = SystemController() |
135
|
|
|
user_controller = UserController() |
136
|
|
|
workspace_controller = WorkspaceController() |
137
|
|
|
comment_controller = CommentController() |
138
|
|
|
html_document_controller = HTMLDocumentController() |
139
|
|
|
thread_controller = ThreadController() |
140
|
|
|
file_controller = FileController() |
141
|
|
|
folder_controller = FolderController() |
142
|
|
|
configurator.include(session_controller.bind, route_prefix=BASE_API_V2) |
143
|
|
|
configurator.include(system_controller.bind, route_prefix=BASE_API_V2) |
144
|
|
|
configurator.include(user_controller.bind, route_prefix=BASE_API_V2) |
145
|
|
|
configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2) |
146
|
|
|
configurator.include(comment_controller.bind, route_prefix=BASE_API_V2) |
147
|
|
|
configurator.include(html_document_controller.bind, route_prefix=BASE_API_V2) # nopep8 |
148
|
|
|
configurator.include(thread_controller.bind, route_prefix=BASE_API_V2) |
149
|
|
|
configurator.include(file_controller.bind, route_prefix=BASE_API_V2) |
150
|
|
|
configurator.include(folder_controller.bind, route_prefix=BASE_API_V2) |
151
|
|
|
|
152
|
|
|
if app_config.FRONTEND_SERVE: |
153
|
|
|
configurator.include('pyramid_mako') |
154
|
|
|
frontend_controller = FrontendController(app_config.FRONTEND_DIST_FOLDER_PATH) # nopep8 |
155
|
|
|
configurator.include(frontend_controller.bind) |
156
|
|
|
|
157
|
|
|
hapic.add_documentation_view( |
158
|
|
|
'/api/v2/doc', |
159
|
|
|
'Tracim v2 API', |
160
|
|
|
'API of Tracim v2', |
161
|
|
|
) |
162
|
|
|
return configurator.make_wsgi_app() |
163
|
|
|
|
164
|
|
|
|
165
|
|
|
def webdav(global_config, **local_settings): |
166
|
|
|
settings = global_config |
167
|
|
|
settings.update(local_settings) |
168
|
|
|
app_factory = WebdavAppFactory( |
169
|
|
|
tracim_config_file_path=settings['__file__'], |
170
|
|
|
) |
171
|
|
|
return app_factory.get_wsgi_app() |
172
|
|
|
|