Coverage for ckanext/udc/error_handler.py: 47%

55 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2026-01-19 23:48 +0000

1from __future__ import annotations 

2from typing import Any, Callable, Collection, KeysView, Optional, Union, cast 

3 

4from ckanext.udc_react.constants import UDC_REACT_PATH 

5from ckan.types import Schema, Context, CKANApp, Response 

6from ckan.common import current_user, CKANConfig, _ 

7from werkzeug.exceptions import ( 

8 default_exceptions, 

9 HTTPException, 

10 Unauthorized, 

11 Forbidden, 

12) 

13from typing import Any, Callable, Collection, KeysView, Optional, Union, cast 

14import ckan.lib.base as base 

15import sys 

16import logging 

17import chalk 

18import ckan.lib.helpers as h 

19import pprint 

20from flask import session, request, Response, abort 

21 

22log = logging.getLogger(__name__) 

23 

24 

25MESSAGE_NOT_LOGGED_IN_ADD_TO_CATALOGUE = _(""" 

26You are not authorized to add to the catalogue. Please login to add a catalogue entry. If you do not have an account, please <a href="/user/register">create one</a>. 

27""") 

28MESSAGE_NOT_LOGGED_IN_CREATE_ORGANIZATION = _(""" 

29You are not authorized to create an organization. Please login to create an organization. If you do not have an account, please <a href="/user/register">create one</a>. 

30""") 

31 

32MESSAGE_NOT_LOGGED_IN_REQUEST_ORGANIZATION_ACCESS = _(""" 

33You are not authorized to request access to an organization. Please login to request access to an organization. If you do not have an account, please <a href="/user/register">create one</a>. 

34""") 

35 

36MESSAGE_NOT_LOGGED_IN_WRONG_USER = _(""" 

37You are not authorized to access this page. Please login with the correct account. 

38""") 

39 

40MESSAGE_NOT_LOGGED_IN_VIEW_ORGANIZATION_ACCESS_REQUESTS = _(""" 

41You are not authorized to view organization access requests. Please login to view organization access requests. 

42""") 

43 

44 

45def clear_and_flash(message, category): 

46 # Remove the error flash message 

47 if "_flashes" in session: 

48 session["_flashes"].clear() 

49 # Add a custom error message and type to the redirect 

50 h.flash(message, category) 

51 

52 

53def override_error_handler(app: CKANApp, config: CKANConfig): 

54 

55 @app.before_request 

56 def display_flashes(): 

57 if request.full_path.endswith(f"came_from=/{UDC_REACT_PATH}/request-organization-access"): 

58 clear_and_flash(MESSAGE_NOT_LOGGED_IN_REQUEST_ORGANIZATION_ACCESS, "alert-warning") 

59 elif f"came_from=/{UDC_REACT_PATH}/request-organization-access/token/" in request.full_path: 

60 clear_and_flash(MESSAGE_NOT_LOGGED_IN_VIEW_ORGANIZATION_ACCESS_REQUESTS, "alert-warning") 

61 

62 @app.errorhandler(Forbidden) 

63 def handle_forbidden(e) -> Union[tuple[str, Optional[int]], Optional[Response]]: 

64 log.info(chalk.red(str(e))) 

65 log.info(pprint.pformat(e.__dict__)) 

66 

67 # Custom error handler for dataset creation "Unauthorized to create a package" 

68 if e.description == "Unauthorized to create a package": 

69 if current_user.is_anonymous: 

70 clear_and_flash(MESSAGE_NOT_LOGGED_IN_ADD_TO_CATALOGUE, "alert-warning") 

71 return h.redirect_to( 

72 controller="user", action="login", next="/catalogue/new" 

73 ) 

74 else: 

75 # Remove the error flash message 

76 session["_flashes"].clear() 

77 # Show a custom error message and redirect to the organization access request page 

78 return h.redirect_to(f"/{UDC_REACT_PATH}/request-organization-access/redirected") 

79 

80 elif e.description == "Unauthorized to create a group": 

81 clear_and_flash(MESSAGE_NOT_LOGGED_IN_CREATE_ORGANIZATION, "alert-warning") 

82 return h.redirect_to( 

83 controller="user", action="login", next="/organization/new" 

84 ) 

85 

86 # Default CKAN error handler below 

87 debug = config.get("debug") 

88 if isinstance(e, HTTPException): 

89 if debug: 

90 log.debug(e, exc_info=sys.exc_info) # type: ignore 

91 else: 

92 log.info(e) 

93 

94 show_login_redirect_link = current_user.is_anonymous and type(e) in ( 

95 Unauthorized, 

96 Forbidden, 

97 ) 

98 extra_vars = { 

99 "code": e.code, 

100 "content": e.description, 

101 "name": e.name, 

102 "show_login_redirect_link": show_login_redirect_link, 

103 } 

104 return base.render("error_document_template.html", extra_vars), e.code 

105 

106 log.error(e, exc_info=sys.exc_info) # type: ignore 

107 extra_vars = {"code": [500], "content": "Internal server error"} 

108 return base.render("error_document_template.html", extra_vars), 500