/*
* Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
*
* 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 controllers;
import com.avaje.ebean.Ebean;
import controllers.compositions.UserCheck;
import data.validation.GsConstraints;
import models.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.data.Form;
import play.data.validation.Constraints;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
import play.mvc.With;
import server.ApplicationContext;
import server.HeaderMessage;
import server.exceptions.ServerException;
import utils.RestUtils;
import views.html.widgets.dashboard.account;
import views.html.widgets.dashboard.angularjs_widget;
import views.html.widgets.dashboard.previewWidget;
import views.html.widgets.dashboard.widgets;
import views.html.widgets.widget;
import views.html.widgets.widgetSinglePage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import static utils.RestUtils.*;
/**
* Widget Admin controller.
*
* @author Igor Goldenberg
*/
public class WidgetAdmin extends Controller
{
private static Logger logger = LoggerFactory.getLogger( WidgetAdmin.class );
public static Result getWidget( String apiKey ){
if ( StringUtils.isEmpty(apiKey)){
return badRequest("apiKey required");
}
Widget widgetItem = Widget.getWidget(apiKey);
if ( widgetItem == null ){//|| !widgetItem.isEnabled()){
return ok();
}
return redirect("/public-folder/angularApps/index.html#/widgets/" + apiKey + "/view?since=" + System.currentTimeMillis());
}
public static Result icon( String apiKey ){
WidgetIcon widgetItem = WidgetIcon.findByWidgetApiKey( apiKey );
if ( widgetItem == null || ArrayUtils.isEmpty(widgetItem.getData()) ){
return ok().as( "image/png");
// return notFound( );
}
return ok( widgetItem.getData() ).as( widgetItem.getContentType() );
}
/**
* This function will save the widget.
* It receives the user's authToken, the widget in JSON format, and icon file in the request body.
*
* This method handles 2 scenarios (not best practice, we know),
* - if widget exists
* - if widget does not exists - we create it
*
*
* Removing an icon is decided if form gets "removeIcon" key.
* @return the widget as JSON - without the icon data.
*/
public static Result postWidget( ){
// read everything from the form.
Http.MultipartFormData body = request().body().asMultipartFormData();
String widgetString = body.asFormUrlEncoded().get( "widget" )[0];
boolean removeIcon = body.asFormUrlEncoded().containsKey("removeIcon");
String authToken = session("authToken");
Http.MultipartFormData.FilePart picture = body.getFile( "icon" );
JsonNode jsonNode = Json.parse(widgetString);
Widget w = null;
User user = null;
if ( jsonNode.has( "id" ) ){
String widgetApiKey = jsonNode.get("apiKey").asText();
w = getWidgetSafely( authToken, widgetApiKey );
}else{
user = User.validateAuthToken( authToken );
}
ObjectMapper mapper = new ObjectMapper();
Form<Widget> validator = form( Widget.class ).bind( jsonNode );
// ignore apiKey errors
validator.errors().remove("apiKey");
if ( validator.hasErrors() ){
new HeaderMessage().populateFormErrors( validator ).apply( response().getHeaders() );
logger.error("trying to save an invalid widget " + validator.toString());
return badRequest( );
}
try {
if ( w == null ){
// creating a new widget.
w = mapper.treeToValue( jsonNode, Widget.class );
w.init();
}else{
mapper.readerForUpdating( w ).treeToValue( jsonNode, Widget.class );
}
logger.info( "successfully turned json to widget [{}]", w );
if ( user != null ){
user.addNewWidget( w );
}
w.update();
w.save( );
w.refresh( );
if ( removeIcon ){
WidgetIcon icon = WidgetIcon.findByWidgetApiKey( w.getApiKey() );
if ( icon != null ){
w.setIcon(null);
w.save();
icon.delete();
}
}
// now lets handle the icon - but only if one was posted.
if ( picture != null ) {
// decide if widget already has an icon or not
WidgetIcon icon = WidgetIcon.findByWidgetApiKey( w.getApiKey() );
if ( icon == null ){
icon = new WidgetIcon();
}
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
byte[] iconData = IOUtils.toByteArray( new FileInputStream( file ) );
icon.setName( fileName );
icon.setContentType( contentType );
icon.setData( iconData );
Ebean.save( icon ); // supports both save and update.
w.setIcon( icon );
w.save( );
return ok( "Added icon successfully" );
}
return ok( Json.toJson( w ) );
} catch ( IOException e ) {
logger.error( "unable to turn body to Json",e );
}
logger.info( "saving widget [{}]", widgetString );
return ok( );
}
//
public static Result getAllWidgets( )
{
User user = User.validateAuthToken(session("authToken"));
List<Widget> list = null;
if ( user.getSession().isAdmin() ) {
list = Widget.find.all(); // Utils.workaround( Widget.find.all() );
// list = Utils.workaround( Widget.find.all() );
}
else {
list = user.getWidgets();
}
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().addMixInAnnotations( Widget.class, Widget.IncludeInstancesMixin.class );
return ok( Json.toJson(list) );
}
public static Result shutdownInstance( String authToken, String instanceId )
{
User.validateAuthToken(authToken);
ApplicationContext.get().getWidgetServer().undeploy( ServerNode.getServerNode( instanceId )); // todo : link to user somehow
return ok(OK_STATUS).as("application/json");
}
@With( UserCheck.class )
public static Result listWidgets( Long userId, String authToken ){
User user = ( User) ctx().args.get("user");
return ok(Json.toJson(Widget.findByUser( user )));
}
public static Result disableWidgetById( Long widgetId )
{
return enableDisableWidget( widgetId, false );
}
private static Result enableDisableWidget( Long widgetId, boolean enabled )
{
getWidgetSafely( session("authToken"), widgetId, true ).setEnabled( enabled ).save();
return ok(OK_STATUS).as("application/json");
}
public static Result enableWidgetById( Long widgetId )
{
return enableDisableWidget( widgetId, true );
}
private static Widget getWidgetSafely( String authToken, Long widgetId, boolean allowAdmin ){
User user = User.validateAuthToken( authToken );
if ( allowAdmin && user.isAdmin()){
return Widget.find.byId( widgetId );
}else{
return Widget.findByUserAndId( user, widgetId );
}
}
private static Widget getWidgetSafely( String authToken, String apiKey )
{
User user = User.validateAuthToken(authToken);
if ( user.isAdmin() ){
return Widget.getWidget(apiKey);
}else{
return Widget.getWidgetByApiKey(user, apiKey);
}
}
public static Result getWidgetById( Long widgetId ){
return ok(Json.toJson(getWidgetSafely(session("authToken"), widgetId, false)));
}
public static Result deleteWidgetById( Long widgetId ){
String authToken = session("authToken");
Widget widget = getWidgetSafely( authToken, widgetId, true );
widget.delete( );
return ok( );
}
public static Result previewWidget( String apiKey ){
Http.Cookie authTokenCookie = request().cookies().get("authToken");
if ( authTokenCookie == null ){
redirect("/");
}
String authToken = authTokenCookie.value();
Widget widget = getWidgetSafely( authToken, apiKey );
return ok( previewWidget.render(widget, request().host()));
}
public static Result regenerateWidgetApiKey( String authToken, String apiKey )
{
Widget w = getWidgetSafely( authToken, apiKey ).regenerateApiKey();
logger.info( "regenerated api key to [{}]", w );
Map<String, Object> result = new HashMap<String, Object>( );
result.put("widget", w);
return ok( Json.toJson( result ) );
}
public static Result headers()
{
Http.Request req = Http.Context.current().request();
StringBuilder sb = new StringBuilder("HEADERS:");
sb.append( "\nRemote address: " ).append( req.remoteAddress() );
Map<String, String[]> headerMap = req.headers();
for (String headerKey : headerMap.keySet())
{
for( String s : headerMap.get(headerKey) )
sb.append( "\n" ).append( headerKey ).append( "=" ).append( s );
}
return ok(sb.toString());
}
public static Result postRequireLogin( String authToken, Long widgetId, boolean requireLogin, String loginVerificationUrl, String webServiceKey ){
Widget widget = getWidgetSafely( authToken, widgetId, false );
if ( widget == null ){
new HeaderMessage().setError(" User is not allowed to edit this widget ").apply(response().getHeaders());
return badRequest();
}
GsConstraints.UrlValidator validator = new GsConstraints.UrlValidator();
if ( !validator.isValid(loginVerificationUrl) ){
new HeaderMessage().addFormError("loginVerificationUrl", "invalid value").apply(response().getHeaders());
return badRequest();
}
widget.setRequireLogin( requireLogin );
widget.setLoginVerificationUrl( loginVerificationUrl );
widget.setWebServiceKey( webServiceKey );
widget.save();
return ok();
}
public static Result postWidgetDescription( String authToken, Long widgetId, String description ){
Widget widget = getWidgetSafely( authToken, widgetId, false );
if ( widget == null ){
new HeaderMessage().setError(" User is not allowed to edit this widget ").apply(response().getHeaders());
return badRequest();
}
widget.setDescription( description );
widget.save( );
return ok( );
}
public static Result newWidgetsPage(){
return ok( angularjs_widget.render() );
}
public static Result getPublicWidgetDetails( String apiKey ){
Widget w = Widget.getWidget(apiKey);
return ok(Json.toJson(new PublicWidget(w)));
}
// public static Result createNewWidget( String widgetId, String authToken, String productName, String productVersion,
// String title, String youtubeVideoUrl, String providerURL,
// String recipeURL, String consolename, String consoleurl, String rootpath, String recipeName, String consoleUrlService )
// {
// User user = User.validateAuthToken(authToken);
// Widget widget = null;
// if ( !NumberUtils.isNumber( widgetId ) ){
// widget = user.createNewWidget( productName, productVersion, title, youtubeVideoUrl, providerURL, recipeURL, consolename, consoleurl, rootpath );
// }else{
// Long widgetIdLong = Long.parseLong( widgetId );
// widget = Widget.findByUserAndId( user, widgetIdLong );
// if ( widget == null ){
// new HeaderMessage().setError( "User is not allowed to edit this widget" ).apply( response().getHeaders() );
// return badRequest( );
// }
// widget.setProductName( productName );
// widget.setProductVersion( productVersion );
// widget.setTitle( title );
// widget.setYoutubeVideoUrl( youtubeVideoUrl );
// widget.setProviderURL( providerURL );
// widget.setRecipeURL( recipeURL );
// widget.setConsoleName( consolename );
// widget.setConsoleURL( consoleurl );
// widget.setRecipeRootPath( rootpath );
// widget.setRecipeName( recipeName );
// widget.setConsoleUrlService( consoleUrlService );
// widget.save();
// }
//
// logger.info( "edited widget : " + widget.toString() );
// return ok( Json.toJson(widget) );
//// return resultAsJson(widget);
// }
}