1import logging
2
3from rest_framework import status
4from rest_framework.authentication import SessionAuthentication
5from rest_framework.permissions import IsAuthenticated
6from rest_framework.response import Response
7from rest_framework.views import APIView
8
9from django.utils.translation import ugettext as _
10
11from seahub.api2.authentication import TokenAuthentication
12from seahub.api2.throttling import UserRateThrottle
13from seahub.api2.utils import api_error
14
15from seaserv import seafile_api
16
17from seahub.constants import PERMISSION_READ_WRITE
18from seahub.repo_api_tokens.models import RepoAPITokens
19from seahub.repo_api_tokens.utils import permission_check_admin_owner
20
21logger = logging.getLogger(__name__)
22
23
24def _get_repo_token_info(repo_token_obj):
25    return {
26        'repo_id': repo_token_obj.repo_id,
27        'app_name': repo_token_obj.app_name,
28        'generated_by': repo_token_obj.generated_by,
29        'permission': repo_token_obj.permission,
30        'api_token': repo_token_obj.token
31    }
32
33
34class RepoAPITokensView(APIView):
35    authentication_classes = (TokenAuthentication, SessionAuthentication)
36    permission_classes = (IsAuthenticated,)
37    throttle_classes = (UserRateThrottle,)
38
39    def get(self, request, repo_id):
40        # resource check
41        repo = seafile_api.get_repo(repo_id)
42        if not repo:
43            error_msg = 'Library %(repo_id)s not found.' % {'repo_id': repo_id}
44            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
45
46        # permission check
47        username = request.user.username
48        if not permission_check_admin_owner(request, username, repo_id):
49            error_msg = 'Permission denied.'
50            return api_error(status.HTTP_403_FORBIDDEN, error_msg)
51
52        rats = RepoAPITokens.objects.filter(repo_id=repo_id).order_by('-generated_at')
53        rat_infos = [_get_repo_token_info(rat) for rat in rats]
54        return Response({'repo_api_tokens': rat_infos})
55
56    def post(self, request, repo_id):
57        # arguments check
58        app_name = request.data.get('app_name')
59        if not app_name:
60            error_msg = 'app_name invalid.'
61            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
62        repo_permission = request.data.get('permission')
63        if repo_permission and repo_permission not in [perm[0] for perm in RepoAPITokens.PERMISSION_CHOICES]:
64            error_msg = 'permission invalid.'
65            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
66        repo_permission = repo_permission if repo_permission else PERMISSION_READ_WRITE
67
68        # resource check
69        repo = seafile_api.get_repo(repo_id)
70        if not repo:
71            error_msg = 'Library %(repo_id)s not found.' % {'repo_id': repo_id}
72            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
73
74        # permission check
75        username = request.user.username
76        if not permission_check_admin_owner(request, username, repo_id):
77            error_msg = 'Permission denied.'
78            return api_error(status.HTTP_403_FORBIDDEN, error_msg)
79
80        rat = RepoAPITokens.objects.filter(app_name=app_name, repo_id=repo_id).first()
81        if rat:
82            error_msg = 'app: %(app)s token already exists.' % {'app': app_name}
83            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
84        try:
85            rat = RepoAPITokens.objects.create_token(app_name=app_name,
86                                                     repo_id=repo_id,
87                                                     username=username,
88                                                     permission=repo_permission)
89        except Exception as e:
90            logger.error('user: %s create repo: %s\'s token error: %s', username, repo_id, e)
91            error_msg = 'Internal Server Error'
92            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
93
94        return Response(_get_repo_token_info(rat))
95
96
97class RepoAPITokenView(APIView):
98    authentication_classes = (TokenAuthentication, SessionAuthentication)
99    permission_classes = (IsAuthenticated,)
100    throttle_classes = (UserRateThrottle,)
101
102    def delete(self, request, repo_id, app_name):
103        # resource check
104        repo = seafile_api.get_repo(repo_id)
105        if not repo:
106            error_msg = 'Library %(repo_id)s not found.' % {'repo_id': repo_id}
107            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
108
109        username = request.user.username
110        # permission check
111        if not permission_check_admin_owner(request, username, repo_id):
112            error_msg = 'Permission denied.'
113            return api_error(status.HTTP_403_FORBIDDEN, error_msg)
114
115        try:
116            rat = RepoAPITokens.objects.filter(repo_id=repo_id, app_name=app_name).first()
117            if not rat:
118                error_msg = 'api token not found'
119                return api_error(status.HTTP_404_NOT_FOUND, error_msg)
120            rat.delete()
121        except Exception as e:
122            logger.error('user: %s delete repo: %s app_name: %s error: %s', username, repo_id, app_name, e)
123            error_msg = 'Internal Server Error'
124            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
125        return Response({'success': True})
126
127    def put(self, request, repo_id, app_name):
128        # arguments check
129        permission = request.data.get('permission')
130        if not permission or permission not in [perm[0] for perm in RepoAPITokens.PERMISSION_CHOICES]:
131            error_msg = 'permission invalid.'
132            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
133
134        # resource check
135        repo = seafile_api.get_repo(repo_id)
136        if not repo:
137            error_msg = 'Library %(repo_id)s not found.' % {'repo_id': repo_id}
138            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
139
140        # permission check
141        username = request.user.username
142        if not permission_check_admin_owner(request, username, repo_id):
143            error_msg = 'Permission denied.'
144            return api_error(status.HTTP_403_FORBIDDEN, error_msg)
145
146        rat = RepoAPITokens.objects.filter(app_name=app_name, repo_id=repo_id).first()
147        if not rat:
148            error_msg = 'api token not found'
149            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
150
151        try:
152            rat.permission = permission
153            rat.save()
154        except Exception as e:
155            logger.error('user: %s update repo: %s app_name: %s error: %s', username, repo_id, app_name, e)
156            error_msg = 'Internal Server Error'
157            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
158
159        return Response(_get_repo_token_info(rat))
160