11from __future__ import absolute_import
22
3+ from rest_framework import serializers , status
34from rest_framework .response import Response
45
56from sentry .api .bases .project import ProjectEndpoint
67from sentry .api .serializers import serialize
78from sentry .models import Rule
9+ from sentry .rules import rules
10+
11+
12+ ValidationError = serializers .ValidationError
13+
14+
15+ class RuleNodeField (serializers .WritableField ):
16+ def __init__ (self , type ):
17+ super (RuleNodeField , self ).__init__ ()
18+ self .type_name = type
19+
20+ def to_native (self , obj ):
21+ return obj
22+
23+ def from_native (self , data ):
24+ if not isinstance (data , dict ):
25+ msg = 'Incorrect type. Expected a mapping, but got %s'
26+ raise ValidationError (msg % type (data ).__name__ )
27+
28+ if 'id' not in data :
29+ raise ValidationError ("Missing attribute 'id'" )
30+
31+ cls = rules .get (data ['id' ], self .type_name )
32+ if cls is None :
33+ msg = "Invalid node. Could not find '%s'"
34+ raise ValidationError (msg % data ['id' ])
35+
36+ if not cls (self .context ['project' ], data ).validate_form ():
37+ raise ValidationError ('Node did not pass validation' )
38+
39+ return data
40+
41+
42+ class ListField (serializers .WritableField ):
43+ def __init__ (self , child ):
44+ self .child = child
45+ super (ListField , self ).__init__ ()
46+
47+ def initialize (self , ** kwargs ):
48+ super (ListField , self ).initialize (** kwargs )
49+ self .child .initialize (** kwargs )
50+
51+ def to_native (self , obj ):
52+ return obj
53+
54+ def from_native (self , data ):
55+ if not isinstance (data , list ):
56+ msg = 'Incorrect type. Expected a mapping, but got %s'
57+ raise ValidationError (msg % type (data ).__name__ )
58+
59+ return map (self .child .from_native , data )
60+
61+
62+ class RuleSerializer (serializers .Serializer ):
63+ name = serializers .CharField (max_length = 64 )
64+ actionMatch = serializers .ChoiceField (choices = (
65+ ('all' , 'all' ),
66+ ('any' , 'any' ),
67+ ('none' , 'none' ),
68+ ))
69+ actions = ListField (
70+ child = RuleNodeField (type = 'action/event' ),
71+ )
72+ conditions = ListField (
73+ child = RuleNodeField (type = 'condition/event' ),
74+ )
75+
76+ def save (self , rule ):
77+ if self .data .get ('name' ):
78+ rule .label = self .data ['name' ]
79+ if self .data .get ('actionMatch' ):
80+ rule .data ['action_match' ] = self .data ['actionMatch' ]
81+ if self .data .get ('actions' ) is not None :
82+ rule .data ['actions' ] = self .data ['actions' ]
83+ if self .data .get ('conditions' ) is not None :
84+ rule .data ['conditions' ] = self .data ['conditions' ]
85+ rule .save ()
86+ return rule
887
988
1089class ProjectRuleDetailsEndpoint (ProjectEndpoint ):
1190 def get (self , request , project , rule_id ):
1291 """
13- Retrieve a rules
92+ Retrieve a rule
1493
1594 Return details on an individual rule.
1695
@@ -22,3 +101,33 @@ def get(self, request, project, rule_id):
22101 id = rule_id ,
23102 )
24103 return Response (serialize (rule , request .user ))
104+
105+ def put (self , request , project , rule_id ):
106+ """
107+ Update a rule
108+
109+ Update various attributes for the given rule.
110+
111+ {method} {path}
112+ {{
113+ "name": "My rule name",
114+ "conditions": [],
115+ "actions": [],
116+ "actionMatch": "all"
117+ }}
118+
119+ """
120+ rule = Rule .objects .get (
121+ project = project ,
122+ id = rule_id ,
123+ )
124+ serializer = RuleSerializer ({
125+ 'actionMatch' : rule .data .get ('action_match' , 'all' ),
126+ }, context = {'project' : project }, data = request .DATA , partial = True )
127+
128+ if serializer .is_valid ():
129+ rule = serializer .save (rule = rule )
130+
131+ return Response (serialize (rule , request .user ))
132+
133+ return Response (serializer .errors , status = status .HTTP_400_BAD_REQUEST )
0 commit comments