package org.rakam.ui;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.google.common.base.Throwables;
import com.google.common.io.ByteStreams;
import com.google.inject.name.Named;
import org.rakam.analysis.JDBCPoolDataSource;
import org.rakam.config.EncryptionConfig;
import org.rakam.server.http.HttpService;
import org.rakam.server.http.RakamHttpRequest;
import org.rakam.server.http.annotations.ApiOperation;
import org.rakam.server.http.annotations.ApiParam;
import org.rakam.server.http.annotations.Authorization;
import org.rakam.server.http.annotations.BodyParam;
import org.rakam.server.http.annotations.CookieParam;
import org.rakam.server.http.annotations.IgnoreApi;
import org.rakam.server.http.annotations.JsonRequest;
import org.rakam.ui.UIPermissionParameterProvider.Project;
import org.rakam.ui.user.WebUser;
import org.rakam.ui.user.WebUserService;
import org.rakam.util.AlreadyExistsException;
import org.rakam.util.JsonHelper;
import org.rakam.util.SuccessMessage;
import org.rakam.util.RakamException;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.util.StringMapper;
import javax.inject.Inject;
import javax.net.ssl.SSLHandshakeException;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED;
import static org.rakam.ui.user.WebUserHttpService.extractUserFromCookie;
@Path("/ui/cluster")
@IgnoreApi
public class ClusterService
extends HttpService
{
private final DBI dbi;
private final WebUserService webUserService;
@Inject
public ClusterService(@Named("ui.metadata.jdbc") JDBCPoolDataSource dataSource,
WebUserService webUserService)
{
dbi = new DBI(dataSource);
this.webUserService = webUserService;
}
@JsonRequest
@ProtectEndpoint(requiresProject = false)
@ApiOperation(value = "Register cluster", authorizations = @Authorization(value = "read_key"))
@Path("/register")
public SuccessMessage register(@javax.inject.Named("user_id") Project project,
@BodyParam Cluster cluster)
{
Optional<WebUser> webUser = webUserService.getUser(project.userId);
if (webUser.get().readOnly) {
throw new RakamException("User is not allowed to register clusters", UNAUTHORIZED);
}
try (Handle handle = dbi.open()) {
try {
handle.createStatement("INSERT INTO rakam_cluster (user_id, api_url, lock_key) VALUES (:userId, :apiUrl, :lockKey)")
.bind("userId", project.userId)
.bind("apiUrl", cluster.apiUrl)
.bind("lockKey", cluster.lockKey).execute();
}
catch (Throwable e) {
int execute = handle.createStatement("UPDATE rakam_cluster SET lock_key = :lock_key WHERE user_id = :userId AND api_url = :apiUrl")
.bind("userId", project.userId)
.bind("apiUrl", cluster.apiUrl)
.bind("lock_key", cluster.lockKey).execute();
if (execute == 0) {
throw new IllegalStateException();
}
return SuccessMessage.success("Lock key is updated");
}
return SuccessMessage.success();
}
}
@JsonRequest
@ProtectEndpoint(requiresProject = false)
@ApiOperation(value = "Delete cluster", authorizations = @Authorization(value = "read_key"))
@Path("/get")
public SuccessMessage delete(@javax.inject.Named("user_id") Project project,
@ApiParam("api_url") String apiUrl)
{
try (Handle handle = dbi.open()) {
handle.createStatement("DELETE FROM rakam_cluster WHERE (user_id, api_url) VALUES (:userId, :apiUrl)")
.bind("userId", project.userId)
.bind("apiUrl", apiUrl).execute();
return SuccessMessage.success();
}
}
@JsonRequest
@ProtectEndpoint(requiresProject = false)
@ApiOperation(value = "List cluster", authorizations = @Authorization(value = "read_key"))
@Path("/list")
@GET
public List<String> list(@javax.inject.Named("user_id") Project project)
{
try (Handle handle = dbi.open()) {
return handle.createQuery("SELECT api_url FROM rakam_cluster WHERE user_id = :userId")
.bind("userId", project.userId).map(StringMapper.FIRST).list();
}
}
public static class Cluster
{
public final String apiUrl;
public final String lockKey;
@JsonCreator
public Cluster(@ApiParam("api_url") String apiUrl, @ApiParam(value = "lock_key", required = false) String lockKey)
{
this.apiUrl = apiUrl;
this.lockKey = lockKey;
}
}
}