Future<AuthenticationResult> BasicAuthenticatorProcess::authenticate( const Request& request) { AuthenticationResult unauthorized; unauthorized.unauthorized = Unauthorized(vector<string>({"Basic realm=\"" + realm_ + "\""})); Option<string> credentials = request.headers.get("Authorization"); if (credentials.isNone()) { return unauthorized; } vector<string> components = strings::split(credentials.get(), " "); if (components.size() != 2 || components[0] != "Basic") { return unauthorized; } Try<string> decoded = base64::decode(components[1]); if (decoded.isError()) { return unauthorized; } vector<string> credential = strings::split(decoded.get(), ":"); if (credential.size() != 2 || !credentials_.contains(credential[0]) || credentials_.at(credential[0]) != credential[1]) { return unauthorized; } AuthenticationResult authenticated; authenticated.principal = credential[0]; return authenticated; }
Future<http::Response> ResourceProviderManagerProcess::api( const http::Request& request, const Option<Principal>& principal) { if (request.method != "POST") { return MethodNotAllowed({"POST"}, request.method); } v1::resource_provider::Call v1Call; // TODO(anand): Content type values are case-insensitive. Option<string> contentType = request.headers.get("Content-Type"); if (contentType.isNone()) { return BadRequest("Expecting 'Content-Type' to be present"); } if (contentType.get() == APPLICATION_PROTOBUF) { if (!v1Call.ParseFromString(request.body)) { return BadRequest("Failed to parse body into Call protobuf"); } } else if (contentType.get() == APPLICATION_JSON) { Try<JSON::Value> value = JSON::parse(request.body); if (value.isError()) { return BadRequest("Failed to parse body into JSON: " + value.error()); } Try<v1::resource_provider::Call> parse = ::protobuf::parse<v1::resource_provider::Call>(value.get()); if (parse.isError()) { return BadRequest("Failed to convert JSON into Call protobuf: " + parse.error()); } v1Call = parse.get(); } else { return UnsupportedMediaType( string("Expecting 'Content-Type' of ") + APPLICATION_JSON + " or " + APPLICATION_PROTOBUF); } Call call = devolve(v1Call); Option<Error> error = validate(call); if (error.isSome()) { return BadRequest( "Failed to validate resource_provider::Call: " + error->message); } ContentType acceptType; if (request.acceptsMediaType(APPLICATION_JSON)) { acceptType = ContentType::JSON; } else if (request.acceptsMediaType(APPLICATION_PROTOBUF)) { acceptType = ContentType::PROTOBUF; } else { return NotAcceptable( string("Expecting 'Accept' to allow ") + "'" + APPLICATION_PROTOBUF + "' or '" + APPLICATION_JSON + "'"); } switch(call.type()) { case Call::UNKNOWN: { return NotImplemented(); } case Call::SUBSCRIBE: { Pipe pipe; OK ok; ok.headers["Content-Type"] = stringify(acceptType); ok.type = http::Response::PIPE; ok.reader = pipe.reader(); HttpConnection http(pipe.writer(), acceptType); subscribe(http, call.subscribe()); return ok; } case Call::UPDATE: { if (!resourceProviders.contains(call.resource_provider_id())) { return BadRequest("Resource provider cannot be found"); } auto resourceProvider = resourceProviders.at(call.resource_provider_id()); update(&resourceProvider, call.update()); return Accepted(); } } UNREACHABLE(); }