1 | # Licensed to the StackStorm, Inc ('StackStorm') under one or more |
||
2 | # contributor license agreements. See the NOTICE file distributed with |
||
3 | # this work for additional information regarding copyright ownership. |
||
4 | # The ASF licenses this file to You under the Apache License, Version 2.0 |
||
5 | # (the "License"); you may not use this file except in compliance with |
||
6 | # the License. You may obtain a copy of the License at |
||
7 | # |
||
8 | # http://www.apache.org/licenses/LICENSE-2.0 |
||
9 | # |
||
10 | # Unless required by applicable law or agreed to in writing, software |
||
11 | # distributed under the License is distributed on an "AS IS" BASIS, |
||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
13 | # See the License for the specific language governing permissions and |
||
14 | # limitations under the License. |
||
15 | |||
16 | import six |
||
17 | |||
18 | from mongoengine import ValidationError |
||
19 | from st2api.controllers import resource |
||
20 | from st2common import log as logging |
||
21 | from st2common.exceptions.actionalias import ActionAliasAmbiguityException |
||
22 | from st2common.exceptions.apivalidation import ValueValidationException |
||
23 | from st2common.models.api.action import ActionAliasAPI |
||
24 | from st2common.persistence.actionalias import ActionAlias |
||
25 | from st2common.rbac.types import PermissionType |
||
26 | from st2common.rbac import utils as rbac_utils |
||
27 | |||
28 | from st2common.router import abort |
||
29 | from st2common.router import Response |
||
30 | from st2common.util.actionalias_matching import get_matching_alias |
||
31 | from st2common.util.actionalias_helpstring import generate_helpstring_result |
||
32 | |||
33 | |||
34 | http_client = six.moves.http_client |
||
35 | |||
36 | LOG = logging.getLogger(__name__) |
||
37 | |||
38 | |||
39 | class ActionAliasController(resource.ContentPackResourceController): |
||
40 | """ |
||
41 | Implements the RESTful interface for ActionAliases. |
||
42 | """ |
||
43 | model = ActionAliasAPI |
||
44 | access = ActionAlias |
||
45 | supported_filters = { |
||
46 | 'name': 'name', |
||
47 | 'pack': 'pack' |
||
48 | } |
||
49 | |||
50 | query_options = { |
||
51 | 'sort': ['pack', 'name'] |
||
52 | } |
||
53 | |||
54 | _custom_actions = { |
||
55 | 'match': ['POST'], |
||
56 | 'help': ['POST'] |
||
57 | } |
||
58 | |||
59 | def get_all(self, sort=None, offset=0, limit=None, requester_user=None, **raw_filters): |
||
60 | return super(ActionAliasController, self)._get_all(sort=sort, |
||
61 | offset=offset, |
||
62 | limit=limit, |
||
63 | raw_filters=raw_filters, |
||
64 | requester_user=requester_user) |
||
65 | |||
66 | def get_one(self, ref_or_id, requester_user): |
||
67 | permission_type = PermissionType.ACTION_ALIAS_VIEW |
||
68 | return super(ActionAliasController, self)._get_one(ref_or_id, |
||
69 | requester_user=requester_user, |
||
70 | permission_type=permission_type) |
||
71 | |||
72 | def match(self, action_alias_match_api): |
||
73 | """ |
||
74 | Find a matching action alias. |
||
75 | |||
76 | Handles requests: |
||
77 | POST /actionalias/match |
||
78 | """ |
||
79 | command = action_alias_match_api.command |
||
80 | |||
81 | try: |
||
82 | format_ = get_matching_alias(command=command) |
||
83 | except ActionAliasAmbiguityException as e: |
||
84 | LOG.exception('Command "%s" matched (%s) patterns.', e.command, len(e.matches)) |
||
85 | return abort(http_client.BAD_REQUEST, str(e)) |
||
86 | |||
87 | # Convert ActionAliasDB to API |
||
88 | action_alias_api = ActionAliasAPI.from_model(format_['alias']) |
||
89 | return { |
||
90 | 'actionalias': action_alias_api, |
||
91 | 'display': format_['display'], |
||
92 | 'representation': format_['representation'], |
||
93 | } |
||
94 | |||
95 | def help(self, filter, pack, limit, offset, **kwargs): |
||
0 ignored issues
–
show
|
|||
96 | """ |
||
97 | Get available help strings for action aliases. |
||
98 | |||
99 | Handles requests: |
||
100 | GET /actionalias/help |
||
101 | """ |
||
102 | try: |
||
103 | aliases_resp = super(ActionAliasController, self)._get_all(**kwargs) |
||
104 | aliases = [ActionAliasAPI(**alias) for alias in aliases_resp.json] |
||
105 | return generate_helpstring_result(aliases, filter, pack, int(limit), int(offset)) |
||
106 | except (TypeError) as e: |
||
107 | LOG.exception('Helpstring request contains an invalid data type: %s.', str(e)) |
||
108 | return abort(http_client.BAD_REQUEST, str(e)) |
||
109 | |||
110 | def post(self, action_alias, requester_user): |
||
111 | """ |
||
112 | Create a new ActionAlias. |
||
113 | |||
114 | Handles requests: |
||
115 | POST /actionalias/ |
||
116 | """ |
||
117 | |||
118 | permission_type = PermissionType.ACTION_ALIAS_CREATE |
||
119 | rbac_utils.assert_user_has_resource_api_permission(user_db=requester_user, |
||
120 | resource_api=action_alias, |
||
121 | permission_type=permission_type) |
||
122 | |||
123 | try: |
||
124 | action_alias_db = ActionAliasAPI.to_model(action_alias) |
||
125 | LOG.debug('/actionalias/ POST verified ActionAliasAPI and formulated ActionAliasDB=%s', |
||
126 | action_alias_db) |
||
127 | action_alias_db = ActionAlias.add_or_update(action_alias_db) |
||
128 | except (ValidationError, ValueError, ValueValidationException) as e: |
||
129 | LOG.exception('Validation failed for action alias data=%s.', action_alias) |
||
130 | abort(http_client.BAD_REQUEST, str(e)) |
||
131 | return |
||
132 | |||
133 | extra = {'action_alias_db': action_alias_db} |
||
134 | LOG.audit('Action alias created. ActionAlias.id=%s' % (action_alias_db.id), extra=extra) |
||
135 | action_alias_api = ActionAliasAPI.from_model(action_alias_db) |
||
136 | |||
137 | return Response(json=action_alias_api, status=http_client.CREATED) |
||
138 | |||
139 | def put(self, action_alias, ref_or_id, requester_user): |
||
140 | """ |
||
141 | Update an action alias. |
||
142 | |||
143 | Handles requests: |
||
144 | PUT /actionalias/1 |
||
145 | """ |
||
146 | action_alias_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) |
||
147 | LOG.debug('PUT /actionalias/ lookup with id=%s found object: %s', ref_or_id, |
||
148 | action_alias_db) |
||
149 | |||
150 | permission_type = PermissionType.ACTION_ALIAS_MODIFY |
||
151 | rbac_utils.assert_user_has_resource_db_permission(user_db=requester_user, |
||
152 | resource_db=action_alias_db, |
||
153 | permission_type=permission_type) |
||
154 | |||
155 | if not hasattr(action_alias, 'id'): |
||
156 | action_alias.id = None |
||
157 | |||
158 | try: |
||
159 | if action_alias.id is not None and action_alias.id is not '' and \ |
||
160 | action_alias.id != ref_or_id: |
||
161 | LOG.warning('Discarding mismatched id=%s found in payload and using uri_id=%s.', |
||
162 | action_alias.id, ref_or_id) |
||
163 | old_action_alias_db = action_alias_db |
||
164 | action_alias_db = ActionAliasAPI.to_model(action_alias) |
||
165 | action_alias_db.id = ref_or_id |
||
166 | action_alias_db = ActionAlias.add_or_update(action_alias_db) |
||
167 | except (ValidationError, ValueError) as e: |
||
168 | LOG.exception('Validation failed for action alias data=%s', action_alias) |
||
169 | abort(http_client.BAD_REQUEST, str(e)) |
||
170 | return |
||
171 | |||
172 | extra = {'old_action_alias_db': old_action_alias_db, 'new_action_alias_db': action_alias_db} |
||
173 | LOG.audit('Action alias updated. ActionAlias.id=%s.' % (action_alias_db.id), extra=extra) |
||
174 | action_alias_api = ActionAliasAPI.from_model(action_alias_db) |
||
175 | |||
176 | return action_alias_api |
||
177 | |||
178 | def delete(self, ref_or_id, requester_user): |
||
179 | """ |
||
180 | Delete an action alias. |
||
181 | |||
182 | Handles requests: |
||
183 | DELETE /actionalias/1 |
||
184 | """ |
||
185 | action_alias_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) |
||
186 | LOG.debug('DELETE /actionalias/ lookup with id=%s found object: %s', ref_or_id, |
||
187 | action_alias_db) |
||
188 | |||
189 | permission_type = PermissionType.ACTION_ALIAS_DELETE |
||
190 | rbac_utils.assert_user_has_resource_db_permission(user_db=requester_user, |
||
191 | resource_db=action_alias_db, |
||
192 | permission_type=permission_type) |
||
193 | |||
194 | try: |
||
195 | ActionAlias.delete(action_alias_db) |
||
196 | except Exception as e: |
||
197 | LOG.exception('Database delete encountered exception during delete of id="%s".', |
||
198 | ref_or_id) |
||
199 | abort(http_client.INTERNAL_SERVER_ERROR, str(e)) |
||
200 | return |
||
201 | |||
202 | extra = {'action_alias_db': action_alias_db} |
||
203 | LOG.audit('Action alias deleted. ActionAlias.id=%s.' % (action_alias_db.id), extra=extra) |
||
204 | |||
205 | return Response(status=http_client.NO_CONTENT) |
||
206 | |||
207 | |||
208 | action_alias_controller = ActionAliasController() |
||
209 |
It is generally discouraged to redefine built-ins as this makes code very hard to read.