@@ -936,177 +936,232 @@ var _ = Describe("V1", func() {
936936 })
937937
938938 Context ("responds with JSON" , func () {
939- BeforeEach (func () {
940- res .WriteOutputs = []testRest.WriteOutput {{BytesWritten : 0 , Error : nil }}
941- })
942-
943- AfterEach (func () {
944- Expect (res .HeaderOutput ).To (Equal (& http.Header {"Content-Type" : []string {"application/json; charset=utf-8" }}))
945- })
946-
947- When ("the path does not contain a user id" , func () {
948- BeforeEach (func () {
949- req .URL .Path = "/v1/users//device_logs"
950- })
951-
952- It ("responds with bad request and expected error in body" , func () {
953- handlerFunc (res , req )
954- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
955- Expect (res .WriteInputs ).To (HaveLen (1 ))
956- errorsTest .ExpectErrorJSON (request .ErrorParameterMissing ("userId" ), res .WriteInputs [0 ])
957- })
958- })
959-
960- When ("the path contains an invalid user id" , func () {
961- BeforeEach (func () {
962- req .URL .Path = "/v1/users/invalid/device_logs"
963- })
964-
965- It ("responds with bad request and expected error in body" , func () {
966- handlerFunc (res , req )
967- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
968- Expect (res .WriteInputs ).To (HaveLen (1 ))
969- errorsTest .ExpectErrorJSON (request .ErrorParameterInvalid ("userId" ), res .WriteInputs [0 ])
970- })
971- })
972-
973- Context ("with content" , func () {
974- var content * blob.DeviceLogsContent
975939
940+ Context ("with clients" , func () {
941+ var details request.AuthDetails
942+ var authClient * authTest.Client
943+ var client * blobTest.Client
944+ var originalUnauthHTTPReq * http.Request
945+ var originalUnauthContext context.Context
976946 BeforeEach (func () {
977- content = blobTest .RandomDeviceLogsContent ()
947+ authClient = authTest .NewClient ()
948+ client = blobTest .NewClient ()
949+ res .WriteOutputs = []testRest.WriteOutput {{BytesWritten : 0 , Error : nil }}
950+ provider .BlobClientOutputs = []blob.Client {client }
951+ provider .AuthClientOutputs = nil
952+ // Because this using the newer authentication
953+ // paradigm, see note in package
954+ // api.RequireAuth for reason why
955+ // provider.AuthClientOutputs is not set. the
956+ // presence of AuthDetails in the context notes
957+ // the user / server has already authenticated.
958+ // The AuthClientOutputs would be non empty if
959+ // an ADDITIONAL call to use the auth client -
960+ // for example to get permissions from user A
961+ // to user B were required
962+
963+ originalUnauthHTTPReq = req .Request
964+ originalUnauthContext = req .Context ()
965+ details = request .NewAuthDetails (request .MethodSessionToken , userID , authTest .NewSessionToken ())
966+ req .Request = req .WithContext (request .NewContextWithAuthDetails (originalUnauthContext , details ))
967+ authClient .GetUserPermissionsStub = func (ctx context.Context , requestUserID string , targetUserID string ) (permission.Permissions , error ) {
968+ authDetails := request .GetAuthDetails (ctx )
969+ if authDetails == nil {
970+ return nil , request .ErrorUnauthenticated ()
971+ }
972+ if authDetails .IsService () || requestUserID == targetUserID {
973+ return permission.Permissions {
974+ permission .Owner : permission.Permission {},
975+ }, nil
976+ }
977+ return nil , request .ErrorUnauthorized ()
978+ }
978979 })
979980
980- JustBeforeEach (func () {
981- req .Body = io .NopCloser (content .Body )
982- if content .DigestMD5 != nil {
983- req .Header .Set ("Digest" , fmt .Sprintf ("md5=%s" , * content .DigestMD5 ))
984- }
985- if content .MediaType != nil {
986- req .Header .Set ("Content-Type" , * content .MediaType )
987- }
988- if content .EndAt != nil {
989- req .Header .Set ("X-Logs-End-At-Time" , content .EndAt .Format (time .RFC3339Nano ))
990- }
991- if content .StartAt != nil {
992- req .Header .Set ("X-Logs-Start-At-Time" , content .StartAt .Format (time .RFC3339Nano ))
993- }
981+ AfterEach (func () {
982+ Expect (res .HeaderOutput ).To (Equal (& http.Header {"Content-Type" : []string {"application/json; charset=utf-8" }}))
994983 })
995984
996- When ("the digest header is invalid " , func () {
985+ When ("the path does not contain a user id " , func () {
997986 BeforeEach (func () {
998- content . DigestMD5 = pointer . FromString ( "invalid" )
987+ req . URL . Path = "/v1/users//device_logs"
999988 })
1000989
1001990 It ("responds with bad request and expected error in body" , func () {
991+ provider .BlobClientOutputs = nil
1002992 handlerFunc (res , req )
1003993 Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1004994 Expect (res .WriteInputs ).To (HaveLen (1 ))
1005- errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ( "Digest " ), res .WriteInputs [0 ])
995+ errorsTest .ExpectErrorJSON (request .ErrorParameterMissing ( "userId " ), res .WriteInputs [0 ])
1006996 })
1007997 })
1008998
1009- When ("the digest header is invalid with multiple values" , func () {
1010- JustBeforeEach (func () {
1011- req .Header .Add ("Digest" , fmt .Sprintf ("md5=%s" , * content .DigestMD5 ))
1012- })
1013-
1014- It ("responds with bad request and expected error in body" , func () {
1015- handlerFunc (res , req )
1016- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1017- Expect (res .WriteInputs ).To (HaveLen (1 ))
1018- errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Digest" ), res .WriteInputs [0 ])
1019- })
1020- })
1021- When ("the digest header is missing" , func () {
999+ When ("the path contains an invalid user id" , func () {
10221000 BeforeEach (func () {
1023- content . DigestMD5 = nil
1001+ req . URL . Path = "/v1/users/invalid/device_logs"
10241002 })
10251003
10261004 It ("responds with bad request and expected error in body" , func () {
1005+ provider .BlobClientOutputs = nil
10271006 handlerFunc (res , req )
10281007 Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
10291008 Expect (res .WriteInputs ).To (HaveLen (1 ))
1030- errorsTest .ExpectErrorJSON (request .ErrorHeaderMissing ( "Digest " ), res .WriteInputs [0 ])
1009+ errorsTest .ExpectErrorJSON (request .ErrorParameterInvalid ( "userId " ), res .WriteInputs [0 ])
10311010 })
10321011 })
10331012
1034- When ("the content type header is missing" , func () {
1013+ Context ("with content" , func () {
1014+ var content * blob.DeviceLogsContent
1015+
10351016 BeforeEach (func () {
1036- content . MediaType = nil
1017+ content = blobTest . RandomDeviceLogsContent ()
10371018 })
10381019
1039- It ("responds with bad request and expected error in body" , func () {
1040- handlerFunc (res , req )
1041- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1042- Expect (res .WriteInputs ).To (HaveLen (1 ))
1043- errorsTest .ExpectErrorJSON (request .ErrorHeaderMissing ("Content-Type" ), res .WriteInputs [0 ])
1020+ JustBeforeEach (func () {
1021+ req .Body = io .NopCloser (content .Body )
1022+ if content .DigestMD5 != nil {
1023+ req .Header .Set ("Digest" , fmt .Sprintf ("md5=%s" , * content .DigestMD5 ))
1024+ }
1025+ if content .MediaType != nil {
1026+ req .Header .Set ("Content-Type" , * content .MediaType )
1027+ }
1028+ if content .EndAt != nil {
1029+ req .Header .Set ("X-Logs-End-At-Time" , content .EndAt .Format (time .RFC3339Nano ))
1030+ }
1031+ if content .StartAt != nil {
1032+ req .Header .Set ("X-Logs-Start-At-Time" , content .StartAt .Format (time .RFC3339Nano ))
1033+ }
10441034 })
1045- })
10461035
1047- When ("the content type header is invalid" , func () {
1048- BeforeEach (func () {
1049- content .MediaType = pointer .FromString ("invalid type" )
1036+ When ("the digest header is invalid" , func () {
1037+ BeforeEach (func () {
1038+ content .DigestMD5 = pointer .FromString ("invalid" )
1039+ })
1040+
1041+ It ("responds with bad request and expected error in body" , func () {
1042+ provider .BlobClientOutputs = nil
1043+ handlerFunc (res , req )
1044+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1045+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1046+ errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Digest" ), res .WriteInputs [0 ])
1047+ })
10501048 })
10511049
1052- It ("responds with bad request and expected error in body" , func () {
1053- handlerFunc (res , req )
1054- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1055- Expect (res .WriteInputs ).To (HaveLen (1 ))
1056- errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Content-Type" ), res .WriteInputs [0 ])
1050+ When ("the digest header is invalid with multiple values" , func () {
1051+ JustBeforeEach (func () {
1052+ req .Header .Add ("Digest" , fmt .Sprintf ("md5=%s" , * content .DigestMD5 ))
1053+ })
1054+
1055+ It ("responds with bad request and expected error in body" , func () {
1056+ provider .BlobClientOutputs = nil
1057+ handlerFunc (res , req )
1058+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1059+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1060+ errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Digest" ), res .WriteInputs [0 ])
1061+ })
10571062 })
1058- })
1063+ When ("the digest header is missing" , func () {
1064+ BeforeEach (func () {
1065+ content .DigestMD5 = nil
1066+ })
10591067
1060- When ("the content type header is invalid with multiple values" , func () {
1061- JustBeforeEach (func () {
1062- req .Header .Add ("Content-Type" , * content .MediaType )
1068+ It ("responds with bad request and expected error in body" , func () {
1069+ provider .BlobClientOutputs = nil
1070+ handlerFunc (res , req )
1071+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1072+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1073+ errorsTest .ExpectErrorJSON (request .ErrorHeaderMissing ("Digest" ), res .WriteInputs [0 ])
1074+ })
10631075 })
10641076
1065- It ("responds with bad request and expected error in body" , func () {
1066- handlerFunc (res , req )
1067- Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1068- Expect (res .WriteInputs ).To (HaveLen (1 ))
1069- errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Content-Type" ), res .WriteInputs [0 ])
1077+ When ("the content type header is missing" , func () {
1078+ BeforeEach (func () {
1079+ content .MediaType = nil
1080+ })
1081+
1082+ It ("responds with bad request and expected error in body" , func () {
1083+ provider .BlobClientOutputs = nil
1084+ handlerFunc (res , req )
1085+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1086+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1087+ errorsTest .ExpectErrorJSON (request .ErrorHeaderMissing ("Content-Type" ), res .WriteInputs [0 ])
1088+ })
10701089 })
1071- })
10721090
1073- Context ("with clients" , func () {
1074- var authClient * authTest.Client
1075- var client * blobTest.Client
1091+ When ("the content type header is invalid" , func () {
1092+ BeforeEach (func () {
1093+ content .MediaType = pointer .FromString ("invalid type" )
1094+ })
10761095
1077- BeforeEach (func () {
1078- authClient = authTest .NewClient ()
1079- client = blobTest .NewClient ()
1080- provider .BlobClientOutputs = []blob.Client {client }
1081- provider .AuthClientOutputs = []auth.Client {authClient }
1096+ It ("responds with bad request and expected error in body" , func () {
1097+ provider .BlobClientOutputs = nil
1098+ handlerFunc (res , req )
1099+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1100+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1101+ errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Content-Type" ), res .WriteInputs [0 ])
1102+ })
10821103 })
10831104
1084- BeforeEach (func () {
1085- authClient .EnsureAuthorizedUserOutputs = []authTest.EnsureAuthorizedUserOutput {{
1086- AuthorizedUserID : userID ,
1087- Error : nil ,
1088- }}
1105+ When ("the content type header is invalid with multiple values" , func () {
1106+ JustBeforeEach (func () {
1107+ req .Header .Add ("Content-Type" , * content .MediaType )
1108+ })
1109+
1110+ It ("responds with bad request and expected error in body" , func () {
1111+ provider .BlobClientOutputs = nil
1112+ handlerFunc (res , req )
1113+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
1114+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1115+ errorsTest .ExpectErrorJSON (request .ErrorHeaderInvalid ("Content-Type" ), res .WriteInputs [0 ])
1116+ })
10891117 })
10901118
10911119 AfterEach (func () {
1092- Expect (authClient .EnsureAuthorizedUserInputs [0 ].TargetUserID ).To (Equal (userID ))
1093- Expect (authClient .EnsureAuthorizedUserInputs [0 ].AuthorizedPermission ).To (Equal (permission .Write ))
10941120 authClient .AssertOutputsEmpty ()
10951121 client .AssertOutputsEmpty ()
10961122 })
10971123
1098- When ("the client returns an unauthorized error" , func () {
1099- It ("responds with an unauthorized error" , func () {
1124+ When ("unauthenticated" , func () {
1125+ It ("responds with an unauthenticated error" , func () {
1126+ provider .BlobClientOutputs = nil
1127+ provider .AuthClientOutputs = nil
1128+ req .Request = originalUnauthHTTPReq
1129+
1130+ handlerFunc (res , req )
1131+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusUnauthorized }))
1132+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1133+ errorsTest .ExpectErrorJSON (request .ErrorUnauthenticated (), res .WriteInputs [0 ])
1134+ })
1135+ })
1136+ When ("the client uploads for another user" , func () {
1137+ var otherUserID string
1138+ BeforeEach (func () {
1139+ provider .AuthClientOutputs = []auth.Client {authClient }
1140+ otherUserID = userTest .RandomID ()
1141+ })
1142+
1143+ It ("returns an unauthorized error for a user uploading for another user" , func () {
1144+ req .URL .Path = fmt .Sprintf ("/v1/users/%s/device_logs" , otherUserID )
11001145 provider .BlobClientOutputs = nil
1101- authClient .EnsureAuthorizedUserOutputs = []authTest.EnsureAuthorizedUserOutput {{
1102- AuthorizedUserID : "" ,
1103- Error : request .ErrorUnauthorized (),
1104- }}
11051146 handlerFunc (res , req )
11061147 Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusForbidden }))
11071148 Expect (res .WriteInputs ).To (HaveLen (1 ))
11081149 errorsTest .ExpectErrorJSON (request .ErrorUnauthorized (), res .WriteInputs [0 ])
11091150 })
1151+
1152+ It ("services responds successfully" , func () {
1153+ provider .AuthClientOutputs = nil // AuthClient not invoked if already determined to be a service
1154+ details = request .NewAuthDetails (request .MethodServiceSecret , "" , authTest .NewSessionToken ())
1155+ req .Request = req .WithContext (request .NewContextWithAuthDetails (originalUnauthContext , details ))
1156+ req .URL .Path = fmt .Sprintf ("/v1/users/%s/device_logs" , otherUserID )
1157+
1158+ responseResult := blobTest .RandomDeviceLogsBlob ()
1159+ client .CreateDeviceLogsOutputs = []blobTest.CreateDeviceLogsOutput {{Blob : responseResult , Error : nil }}
1160+ handlerFunc (res , req )
1161+ Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusCreated }))
1162+ Expect (res .WriteInputs ).To (HaveLen (1 ))
1163+ Expect (json .Marshal (responseResult )).To (MatchJSON (res .WriteInputs [0 ]))
1164+ })
11101165 })
11111166
11121167 When ("the digest header is specified" , func () {
@@ -1125,6 +1180,7 @@ var _ = Describe("V1", func() {
11251180 It ("responds with a bad request error when the client returns a digests not equal error" , func () {
11261181 err := request .ErrorDigestsNotEqual (cryptoTest .RandomBase64EncodedMD5Hash (), cryptoTest .RandomBase64EncodedMD5Hash ())
11271182 client .CreateDeviceLogsOutputs = []blobTest.CreateDeviceLogsOutput {{Blob : nil , Error : err }}
1183+ provider .BlobClientOutputs = []blob.Client {client }
11281184 handlerFunc (res , req )
11291185 Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusBadRequest }))
11301186 Expect (res .WriteInputs ).To (HaveLen (1 ))
@@ -1133,6 +1189,7 @@ var _ = Describe("V1", func() {
11331189
11341190 It ("responds with an internal server error when the client returns an unknown error" , func () {
11351191 client .CreateDeviceLogsOutputs = []blobTest.CreateDeviceLogsOutput {{Blob : nil , Error : errorsTest .RandomError ()}}
1192+ provider .BlobClientOutputs = []blob.Client {client }
11361193 handlerFunc (res , req )
11371194 Expect (res .WriteHeaderInputs ).To (Equal ([]int {http .StatusInternalServerError }))
11381195 Expect (res .WriteInputs ).To (HaveLen (1 ))
0 commit comments