Test Failed
Push — master ( e380d0...f5671d )
by W
02:58
created

st2api/st2api/controllers/v1/actionalias.py (1 issue)

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
Bug Best Practice introduced by
This seems to re-define the built-in filter.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
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