/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.addthis.hydra.job.web.resources;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import com.addthis.hydra.job.auth.User;
import com.addthis.hydra.job.spawn.Spawn;
import com.addthis.hydra.job.web.SpawnService;
import com.addthis.hydra.job.web.SpawnServiceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("/authentication")
public class AuthenticationResource {
private static final Logger log = LoggerFactory.getLogger(AuthenticationResource.class);
private final Spawn spawn;
private final SpawnServiceConfiguration configuration;
public AuthenticationResource(Spawn spawn) {
this.spawn = spawn;
this.configuration = SpawnServiceConfiguration.SINGLETON;
}
@POST
@Path("/login")
@Produces(MediaType.TEXT_PLAIN)
public Response login(@FormParam("user") String username,
@FormParam("password") String password,
@Context UriInfo uriInfo) {
URI uri = uriInfo.getRequestUri();
boolean usingSSL = (uri.getPort() == configuration.webPortSSL);
try {
String token = spawn.getPermissionsManager().login(username, password, usingSSL);
Response.ResponseBuilder builder;
if (token == null) {
builder = Response.status(Response.Status.UNAUTHORIZED);
builder.entity("Invalid credentials provided");
} else {
builder = Response.ok(token);
}
builder.header("Access-Control-Allow-Origin",
"http://" + uriInfo.getAbsolutePath().getHost() +
":" + configuration.webPort);
builder.header("Access-Control-Allow-Methods", "POST");
return builder.build();
} catch (Exception ex) {
log.warn("Internal error in authentication attempt for user {} with ssl {}", username, usingSSL, ex);
return Response.serverError().entity("internal error").build();
}
}
@POST
@Path("/validate")
@Produces(MediaType.TEXT_PLAIN)
public Response validate(@FormParam("user") String username,
@FormParam("token") String token,
@Context UriInfo uriInfo) {
URI uri = uriInfo.getRequestUri();
boolean usingSSL = (uri.getPort() == configuration.webPortSSL);
try {
User user = spawn.getPermissionsManager().authenticate(username, token);
Response.ResponseBuilder builder = Response.ok(Boolean.toString(user != null));
builder.header("Access-Control-Allow-Origin",
"http://" + uriInfo.getAbsolutePath().getHost() +
":" + configuration.webPort);
builder.header("Access-Control-Allow-Methods", "POST");
return builder.build();
} catch (Exception ex) {
log.warn("Internal error in validation attempt for user {} with ssl {}", username, usingSSL, ex);
return Response.serverError().entity("internal error").build();
}
}
@POST
@Path("/sudo")
@Produces(MediaType.TEXT_PLAIN)
public Response sudo(@FormParam("user") String username,
@FormParam("password") String password,
@Context UriInfo uriInfo) {
URI uri = uriInfo.getRequestUri();
boolean usingSSL = (uri.getPort() == configuration.webPortSSL);
try {
String sudoToken = spawn.getPermissionsManager().sudo(username, password, usingSSL);
Response.ResponseBuilder builder;
if (sudoToken == null) {
builder = Response.status(Response.Status.UNAUTHORIZED);
builder.entity("Invalid credentials provided");
} else {
builder = Response.ok(sudoToken);
}
builder.header("Access-Control-Allow-Origin",
"http://" + uriInfo.getAbsolutePath().getHost() +
":" + configuration.webPort);
builder.header("Access-Control-Allow-Methods", "POST");
return builder.build();
} catch (Exception ex) {
log.warn("Internal error in sudo attempt for user {} with ssl {}", username, usingSSL, ex);
return Response.serverError().entity(ex.toString()).build();
}
}
@POST
@Path("/evict")
public Response evict(@FormParam("user") String user,
@FormParam("token") String token,
@FormParam("sudo") String sudo,
@FormParam("target") String target) {
Response.ResponseBuilder builder;
if (target == null) {
builder = Response.status(Response.Status.BAD_REQUEST);
builder.entity("target argument missing");
} else if ((target.equals(user) && (spawn.getPermissionsManager().authenticate(user, token) == null)) ||
(!target.equals(user) && !spawn.getPermissionsManager().adminAction(user, token, sudo))) {
builder = Response.status(Response.Status.UNAUTHORIZED);
builder.entity("Invalid credentials provided");
} else if (!spawn.getPermissionsManager().evict(target)) {
builder = Response.ok("User " + target + " was not logged in");
} else {
builder = Response.ok("User " + target + " evicted");
}
return builder.build();
}
@POST
@Path("/logout")
public void logout(@FormParam("user") String username,
@FormParam("token") String token,
@Context UriInfo uriInfo) {
URI uri = uriInfo.getRequestUri();
boolean usingSSL = (uri.getPort() == configuration.webPortSSL);
try {
spawn.getPermissionsManager().logout(username, token);
} catch (Exception ex) {
log.warn("Internal error in logout attempt for user {} with ssl {}", username, usingSSL, ex);
}
}
}