@@ -1030,6 +1030,73 @@ def hasPermission(s, p, classname=None, d=None, e=None, **kw):
10301030 os .remove (SENDMAILDEBUG )
10311031 #raise ValueError
10321032
1033+ def testRestCsrfProtection (self ):
1034+ # set the password for admin so we can log in.
1035+ passwd = password .Password ('admin' )
1036+ self .db .user .set ('1' , password = passwd )
1037+
1038+ out = []
1039+ def wh (s ):
1040+ out .append (s )
1041+
1042+ # rest has no form content
1043+ form = cgi .FieldStorage ()
1044+ form .list = [
1045+ cgi .MiniFieldStorage ('title' , 'A new issue' ),
1046+ cgi .MiniFieldStorage ('status' , '1' ),
1047+ cgi .MiniFieldStorage ('pretty' , 'false' ),
1048+ cgi .MiniFieldStorage ('@apiver' , '1' ),
1049+ ]
1050+ cl = client .Client (self .instance , None ,
1051+ {'REQUEST_METHOD' :'POST' ,
1052+ 'PATH_INFO' :'rest/data/issue' ,
1053+ 'CONTENT_TYPE' : 'application/x-www-form-urlencoded' ,
1054+ 'HTTP_AUTHORIZATION' : 'Basic YWRtaW46YWRtaW4=' ,
1055+ 'HTTP_REFERER' : 'http://whoami.com/path/' ,
1056+ 'HTTP_ACCEPT' : "application/json;version=1"
1057+ }, form )
1058+ cl .db = self .db
1059+ cl .base = 'http://whoami.com/path/'
1060+ cl ._socket_op = lambda * x : True
1061+ cl ._error_message = []
1062+ cl .request = MockNull ()
1063+ h = { 'content-type' : 'application/json' ,
1064+ 'accept' : 'application/json' }
1065+ cl .request .headers = MockNull (** h )
1066+
1067+ cl .write = wh # capture output
1068+
1069+ # Should return explanation because content type is text/plain
1070+ # and not text/xml
1071+ cl .handle_rest ()
1072+ self .assertEqual (out [0 ], "<class 'roundup.exceptions.UsageError'>: Required Header Missing\n " )
1073+ del (out [0 ])
1074+
1075+ cl = client .Client (self .instance , None ,
1076+ {'REQUEST_METHOD' :'POST' ,
1077+ 'PATH_INFO' :'rest/data/issue' ,
1078+ 'CONTENT_TYPE' : 'application/x-www-form-urlencoded' ,
1079+ 'HTTP_AUTHORIZATION' : 'Basic YWRtaW46YWRtaW4=' ,
1080+ 'HTTP_REFERER' : 'http://whoami.com/path/' ,
1081+ 'HTTP_X_REQUESTED_WITH' : 'rest' ,
1082+ 'HTTP_ACCEPT' : "application/json;version=1"
1083+ }, form )
1084+ cl .db = self .db
1085+ cl .base = 'http://whoami.com/path/'
1086+ cl ._socket_op = lambda * x : True
1087+ cl ._error_message = []
1088+ cl .request = MockNull ()
1089+ h = { 'content-type' : 'application/json' ,
1090+ 'accept' : 'application/json;version=1' }
1091+ cl .request .headers = MockNull (** h )
1092+
1093+ cl .write = wh # capture output
1094+
1095+ # Should work as all required headers are present.
1096+ cl .handle_rest ()
1097+ self .assertEqual (out [0 ], '{"data": {"link": "http://tracker.example/cgi-bin/roundup.cgi/bugs/rest/data/issue/1", "id": "1"}}\n ' )
1098+ del (out [0 ])
1099+
10331100 def testXmlrpcCsrfProtection (self ):
10341101 # set the password for admin so we can log in.
10351102 passwd = password .Password ('admin' )
0 commit comments