001/* 002 * Copyright (c) 2017 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2017-08-23 22:42:39 -0700 (Wed, 23 Aug 2017) $' 007 * '$Revision: 1375 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029package org.kepler.webview.server.handler; 030 031import java.net.HttpURLConnection; 032import java.util.Set; 033 034import org.kepler.webview.server.WebViewConfiguration; 035import org.kepler.webview.server.WebViewServer; 036import org.kepler.webview.server.auth.AuthUtilities; 037 038import io.vertx.core.file.FileSystem; 039import io.vertx.core.json.JsonArray; 040import io.vertx.core.json.JsonObject; 041import io.vertx.ext.web.RoutingContext; 042 043/** Handler for logins. 044 * 045 * @author Daniel Crawl 046 * @version $Id: LoginHandler.java 1375 2017-08-24 05:42:39Z crawl $ 047 */ 048public class LoginHandler extends BaseHandler { 049 050 public LoginHandler(WebViewServer server) { 051 super(server); 052 _metadataFileName = WebViewConfiguration.getHttpServerMetadataFileName(); 053 _fileSystem = _server.getVertx().fileSystem(); 054 } 055 056 @Override 057 public void handle(RoutingContext context) { 058 059 final long timestamp = System.currentTimeMillis(); 060 061 /* 062 System.out.println("logged in " + 063 context.user().principal().getString("username") + " " + 064 context.session().id()); 065 */ 066 067 // get the last modified time of the metadata file. 068 _fileSystem.props(_metadataFileName, propsResult -> { 069 if(propsResult.succeeded()) { 070 // see if file was modified since we last read it 071 if(propsResult.result().lastModifiedTime() > _metadataLastModifiedTime || _metadataJson == null) { 072 _metadataLastModifiedTime = propsResult.result().lastModifiedTime(); 073 074 // read metadata file 075 _fileSystem.readFile(_metadataFileName, readResult -> { 076 if(readResult.succeeded()) { 077 // update the cached json 078 try { 079 _metadataJson = readResult.result().toJsonArray(); 080 } catch(Throwable t) { 081 context.response() 082 .putHeader("Content-Type", "text/plain") 083 .setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR) 084 .setStatusMessage("Could not access metadata.") 085 .end(); 086 System.err.println("Error reading metadata file " + 087 _metadataFileName + ": " + t.getMessage()); 088 _server.log(context.request(), context.user(), HttpURLConnection.HTTP_INTERNAL_ERROR, timestamp); 089 return; 090 } 091 // send metadata json in response 092 _sendMetadata(context, timestamp); 093 } else { 094 context.response() 095 .putHeader("Content-Type", "text/plain") 096 .setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR) 097 .setStatusMessage("Could not access metadata.") 098 .end(); 099 System.err.println("Could not read metadata " + 100 _metadataFileName + ": " + readResult.cause().getMessage()); 101 _server.log(context.request(), context.user(), HttpURLConnection.HTTP_INTERNAL_ERROR, timestamp); 102 } 103 }); 104 } else { 105 // send cached metadata json in response 106 _sendMetadata(context, timestamp); 107 } 108 } else { 109 context.response() 110 .putHeader("Content-Type", "text/plain") 111 .setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR) 112 .setStatusMessage("Could not access metadata.") 113 .end(); 114 System.err.println("Could not get properties for metadata " + 115 _metadataFileName + ": " + propsResult.cause().getMessage()); 116 _server.log(context.request(), context.user(), HttpURLConnection.HTTP_INTERNAL_ERROR, timestamp); 117 } 118 }); 119 } 120 121 /** Send metadata JSON in response. 122 * @param context The vertx routing context. 123 * @param timestamp The timestamp of the request. 124 */ 125 private void _sendMetadata(RoutingContext context, long timestamp) { 126 127 // construct the response json 128 129 JsonObject principal = context.user().principal(); 130 Set<String> userGroups = AuthUtilities.getGroups(context.user()); 131 132 JsonObject returnJson = new JsonObject(); 133 134 // add the username 135 returnJson.put("username", principal.getString("username")); 136 returnJson.put("fullname", principal.getString("fullname")); 137 138 // add the groups 139 JsonArray groupsArray = new JsonArray(); 140 for(String groupName : userGroups) { 141 groupsArray.add(groupName); 142 } 143 returnJson.put("groups", groupsArray); 144 145 // add metadata 146 147 if(userGroups.contains("admin")) { 148 returnJson.put("metadata", _metadataJson.copy()); 149 } else { 150 JsonArray returnMetadataJson = new JsonArray(); 151 for(int i = 0; i < _metadataJson.size(); i++) { 152 JsonObject m = _metadataJson.getJsonObject(i); 153 boolean inGroup = false; 154 if(!m.containsKey("groups")) { 155 inGroup = true; 156 } else { 157 JsonArray groupsList = m.getJsonArray("groups"); 158 for(int j = 0; j < groupsList.size(); j++) { 159 if(userGroups.contains(groupsList.getString(j))) { 160 inGroup = true; 161 break; 162 } 163 } 164 } 165 166 if(inGroup) { 167 returnMetadataJson.add(m.copy()); 168 } 169 }; 170 returnJson.put("metadata", returnMetadataJson); 171 } 172 173 //System.out.println(returnJson.encodePrettily()); 174 175 context.response().putHeader("Content-Type", "application/json") 176 .end(returnJson.encode()); 177 _server.log(context.request(), context.user(), HttpURLConnection.HTTP_OK, timestamp); 178 } 179 180 /** Vertx file system. */ 181 private FileSystem _fileSystem; 182 183 /** Metadata file name. */ 184 private String _metadataFileName; 185 186 /** Last modified time of metadata file. */ 187 private long _metadataLastModifiedTime = -1; 188 189 /** Metadata JSON cached from reading metadata file. */ 190 private JsonArray _metadataJson; 191}