@ -21,6 +21,7 @@ import static java.net.HttpURLConnection.*;
@@ -21,6 +21,7 @@ import static java.net.HttpURLConnection.*;
import static java.nio.charset.StandardCharsets.UTF_8 ;
import static java.text.MessageFormat.format ;
import static java.time.temporal.ChronoUnit.DAYS ;
import static java.util.Optional.empty ;
import com.sun.net.httpserver.HttpExchange ;
import de.srsoftware.tools.Path ;
@ -94,10 +95,10 @@ public class UserModule extends BaseHandler {
@@ -94,10 +95,10 @@ public class UserModule extends BaseHandler {
}
private boolean deleteService ( HttpExchange ex , UmbrellaUser user , String serviceName ) throws IOException {
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return unauthorized ( ex ) ;
try {
logins . delete ( serviceName ) ;
return sendEmptyResponse ( HTTP_OK , ex ) ;
return ok ( ex ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
@ -118,55 +119,55 @@ public class UserModule extends BaseHandler {
@@ -118,55 +119,55 @@ public class UserModule extends BaseHandler {
try {
logins . unlink ( ForeignLogin . of ( serviceId , foreignId , user . id ( ) ) ) ;
return sendEmptyResponse ( HTTP_OK , ex ) ;
return ok ( ex ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
}
private Optional < UmbrellaUser > loadUser ( Optional < Token > sessionToken ) throws UmbrellaException {
if ( sessionToken . isEmpty ( ) ) return empty ( ) ;
var session = users . load ( sessionToken . get ( ) ) ;
return Optional . of ( users . load ( session ) ) ;
}
private Optional < UmbrellaUser > loadUser ( HttpExchange ex ) throws UmbrellaException {
return loadUser ( SessionToken . from ( ex ) . map ( Token : : of ) ) ;
}
@Override
public boolean doDelete ( Path path , HttpExchange ex ) throws IOException {
UmbrellaUser user = null ;
var sessionToken = SessionToken . from ( ex ) . map ( Token : : of ) ;
if ( sessionToken . isPresent ( ) ) try {
user = users . load ( users . load ( sessionToken . get ( ) ) ) ;
} catch ( UmbrellaException e ) {
LOG . log ( WARNING , e ) ;
try {
var user = loadUser ( ex ) ;
addCors ( ex ) ;
var head = path . pop ( ) ;
if ( OIDC . equals ( head ) ) return user . isEmpty ( ) ? unauthorized ( ex ) : deleteOIDC ( ex , user . get ( ) , path ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
addCors ( ex ) ;
var head = path . pop ( ) ;
switch ( head ) {
case OIDC : return deleteOIDC ( ex , user , path ) ;
} ;
return super . doDelete ( path , ex ) ;
}
@Override
public boolean doGet ( Path path , HttpExchange ex ) throws IOException {
UmbrellaUser user = null ;
var sessionToken = SessionToken . from ( ex ) . map ( Token : : of ) ;
if ( sessionToken . isPresent ( ) ) try {
user = users . load ( users . load ( sessionToken . get ( ) ) ) ;
} catch ( UmbrellaException e ) {
LOG . log ( WARNING , e ) ;
}
addCors ( ex ) ;
var head = path . pop ( ) ;
switch ( head ) {
case LIST : return getUserList ( ex , user ) ;
case LOGOUT : return logout ( ex , sessionToken ) ;
case OIDC : return getOIDC ( ex , user , path ) ;
case VALIDATE_OTP : return validateOtpToken ( ex , path . pop ( ) ) ;
case WHOAMI : return getUser ( ex , user ) ;
} ;
try {
var user = loadUser ( sessionToken ) ;
addCors ( ex ) ;
var head = path . pop ( ) ;
switch ( head ) {
case LIST : return user . isEmpty ( ) ? unauthorized ( ex ) : getUserList ( ex , user . get ( ) ) ;
case LOGOUT : return logout ( ex , sessionToken ) ;
case OIDC : return getOIDC ( ex , user . orElse ( null ) , path ) ;
case VALIDATE_OTP : return validateOtpToken ( ex , path . pop ( ) ) ;
case WHOAMI : return user . isEmpty ( ) ? unauthorized ( ex ) : sendContent ( ex , user . get ( ) ) ;
} ;
long userId = Long . parseLong ( head ) ;
if ( ! ( user instanceof DbUser dbUser & & ( user . id ( ) = = userId | | dbUser . permissions ( ) . contains ( LIST_USERS ) ) ) ) {
return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
}
if ( user . isEmpty ( ) ) return forbidden ( ex ) ;
if ( ! ( user . get ( ) instanceof DbUser dbUser ) ) return forbidden ( ex ) ;
if ( dbUser . id ( ) = = userId | | dbUser . permissions ( ) . contains ( LIST_USERS ) ) return forbidden ( ex ) ;
return sendContent ( ex , users . load ( userId ) ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
@ -177,56 +178,36 @@ public class UserModule extends BaseHandler {
@@ -177,56 +178,36 @@ public class UserModule extends BaseHandler {
@Override
public boolean doOptions ( Path path , HttpExchange ex ) throws IOException {
return sendEmptyResponse ( 200 , addCors ( ex ) ) ;
return ok ( addCors ( ex ) ) ;
}
public boolean doPatch ( Path path , HttpExchange ex ) throws IOException {
addCors ( ex ) ;
var sessionToken = SessionToken . from ( ex ) ;
if ( sessionToken . isEmpty ( ) ) return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
UmbrellaUser requestingUser ;
try {
Session session = users . load ( Token . of ( sessionToken . get ( ) ) ) ;
requestingUser = users . load ( session ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
var head = path . pop ( ) ;
long userId ;
String head = null ;
try {
var requestingUser = loadUser ( ex ) ;
head = path . pop ( ) ;
long userId ;
if ( head = = null | | head . isBlank ( ) ) return sendContent ( ex , HTTP_UNPROCESSABLE , "User id missing!" ) ;
if ( PASSWORD . equals ( head ) ) return patchPassword ( ex , requestingUser ) ;
if ( OIDC . equals ( head ) ) return patchService ( ex , path . pop ( ) , requestingUser ) ;
if ( requestingUser . isEmpty ( ) ) return unauthorized ( ex ) ;
if ( PASSWORD . equals ( head ) ) return patchPassword ( ex , requestingUser . get ( ) ) ;
if ( OIDC . equals ( head ) ) return patchService ( ex , path . pop ( ) , requestingUser . get ( ) ) ;
userId = Long . parseLong ( head ) ;
} catch ( NumberFormatException e ) {
return sendContent ( ex , HTTP_UNPROCESSABLE , "Invalid user id: " + head ) ;
}
DbUser editedUser ;
try {
editedUser = ( DbUser ) users . load ( userId ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
if ( requestingUser . id ( ) ! = userId & & ( ! ( requestingUser instanceof DbUser dbUser ) | | ! dbUser . permissions ( ) . contains ( UPDATE_USERS ) ) ) {
return sendContent ( ex , HTTP_FORBIDDEN , "You are not allowed to update user " + editedUser . name ( ) ) ;
}
JSONObject json ;
try {
json = json ( ex ) ;
} catch ( Exception e ) {
LOG . log ( WARNING , "Request does not contain valid JSON" , e ) ;
return sendContent ( ex , HTTP_BAD_REQUEST , "Body contains no JSON data" ) ;
}
DbUser editedUser = ( DbUser ) users . load ( userId ) ;
if ( ! ( requestingUser . get ( ) instanceof DbUser dbUser ) | | ! dbUser . permissions ( ) . contains ( UPDATE_USERS ) ) return sendContent ( ex , HTTP_FORBIDDEN , "You are not allowed to update user " + editedUser . name ( ) ) ;
try {
JSONObject json ;
try {
json = json ( ex ) ;
} catch ( Exception e ) {
LOG . log ( WARNING , "Request does not contain valid JSON" , e ) ;
return sendContent ( ex , HTTP_BAD_REQUEST , "Body contains no JSON data" ) ;
}
return update ( ex , editedUser , json ) ;
} catch ( NumberFormatException e ) {
return sendContent ( ex , HTTP_UNPROCESSABLE , "Invalid user id: " + head ) ;
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
@ -273,14 +254,8 @@ public class UserModule extends BaseHandler {
@@ -273,14 +254,8 @@ public class UserModule extends BaseHandler {
if ( ! ( resp instanceof JSONObject json ) ) return sendContent ( ex , HTTP_BAD_REQUEST , format ( "{0} did not return JSON!" , location ) ) ;
if ( ! json . has ( ID_TOKEN ) ) return sendContent ( ex , HTTP_FAILED_DEPENDENCY , "Missing ID token – token exchange failed!" ) ;
var idToken = json . getString ( ID_TOKEN ) ;
Optional < Token > optToken = SessionToken . from ( ex ) . map ( Token : : of ) ;
Optional < UmbrellaUser > optUser = Optional . empty ( ) ;
if ( optToken . isPresent ( ) ) {
Session session = users . load ( optToken . get ( ) ) ;
optUser = Optional . of ( users . load ( session ) ) ;
}
var oidcUserId = verifyAndGetUserId ( idToken , state ) ;
var optUser = loadUser ( ex ) ;
if ( optUser . isPresent ( ) ) { // user already logged in – this is the case when the new id gets assigned
var currentUser = optUser . get ( ) ;
var assignment = new ForeignLogin ( state . loginService . name ( ) , oidcUserId , currentUser . id ( ) ) ;
@ -298,7 +273,7 @@ public class UserModule extends BaseHandler {
@@ -298,7 +273,7 @@ public class UserModule extends BaseHandler {
}
private boolean getConnectedServices ( HttpExchange ex , UmbrellaUser user ) throws IOException {
if ( user = = null ) return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
if ( user = = null ) return unauthorized ( ex ) ;
try {
var connections = logins . listAssignments ( user . id ( ) ) . stream ( ) . map ( ForeignLogin : : toMap ) ;
return sendContent ( ex , connections ) ;
@ -321,7 +296,7 @@ public class UserModule extends BaseHandler {
@@ -321,7 +296,7 @@ public class UserModule extends BaseHandler {
}
private boolean getOIDC ( HttpExchange ex , UmbrellaUser user , String serviceId ) throws IOException {
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return forbidden ( ex ) ;
try {
return sendContent ( ex , logins . loadLoginService ( serviceId ) . toMap ( ) ) ;
} catch ( UmbrellaException e ) {
@ -381,7 +356,7 @@ public class UserModule extends BaseHandler {
@@ -381,7 +356,7 @@ public class UserModule extends BaseHandler {
}
private boolean getServiceList ( HttpExchange ex , UmbrellaUser user ) throws IOException {
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return forbidden ( ex ) ;
try {
var services = logins . listLoginServices ( ) . stream ( ) . map ( LoginService : : toMap ) ;
return sendContent ( ex , services ) ;
@ -392,11 +367,6 @@ public class UserModule extends BaseHandler {
@@ -392,11 +367,6 @@ public class UserModule extends BaseHandler {
}
}
private boolean getUser ( HttpExchange ex , UmbrellaUser user ) throws IOException {
if ( user ! = null ) return sendContent ( ex , user ) ;
return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
}
private boolean getUserList ( HttpExchange ex , UmbrellaUser user ) throws IOException {
if ( ! ( user instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( LIST_USERS ) ) ) return sendContent ( ex , HTTP_FORBIDDEN , "You are not allowed to list users!" ) ;
try {
@ -408,11 +378,10 @@ public class UserModule extends BaseHandler {
@@ -408,11 +378,10 @@ public class UserModule extends BaseHandler {
}
private boolean impersonate ( HttpExchange ex , Long targetId ) throws IOException {
var sessionToken = SessionToken . from ( ex ) . map ( Token : : of ) ;
if ( sessionToken . isEmpty ( ) ) return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
try {
var requestingUser = users . load ( users . load ( sessionToken . get ( ) ) ) ;
if ( ! ( requestingUser instanceof DbUser dbUser & & dbUser . permissions ( ) . contains ( PERMISSION . IMPERSONATE ) ) ) return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
var requestingUser = loadUser ( ex ) ;
if ( ! ( requestingUser . isPresent ( ) & & requestingUser . get ( ) instanceof DbUser dbUser ) ) return unauthorized ( ex ) ;
if ( ! dbUser . permissions ( ) . contains ( PERMISSION . IMPERSONATE ) ) return forbidden ( ex ) ;
if ( targetId = = null ) return sendContent ( ex , HTTP_UNPROCESSABLE , "user id missing" ) ;
var targetUser = users . load ( targetId ) ;
users . getSession ( targetUser ) . cookie ( ) . addTo ( ex ) ;
@ -431,9 +400,9 @@ public class UserModule extends BaseHandler {
@@ -431,9 +400,9 @@ public class UserModule extends BaseHandler {
}
new SessionToken ( token . toString ( ) , "/" , Instant . now ( ) . minus ( 1 , DAYS ) , true ) . addTo ( ex ) ;
return sendEmptyResponse ( HTTP_OK , ex ) ;
return ok ( ex ) ;
}
return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
return unauthorized ( ex ) ;
}
@ -468,11 +437,11 @@ public class UserModule extends BaseHandler {
@@ -468,11 +437,11 @@ public class UserModule extends BaseHandler {
}
private boolean postCreate ( HttpExchange ex ) throws IOException {
var sessionToken = SessionToken . from ( ex ) . map ( Token : : of ) ;
if ( sessionToken . isEmpty ( ) ) return sendEmptyResponse ( HTTP_UNAUTHORIZED , ex ) ;
try {
var u = users . load ( users . load ( sessionToken . get ( ) ) ) ;
if ( ! ( u instanceof DbUser requestingUser & & requestingUser . permissions ( ) . contains ( PERMISSION . CREATE_USERS ) ) ) return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
var optUser = loadUser ( ex ) ;
if ( ! ( optUser . isPresent ( ) & & optUser . get ( ) instanceof DbUser dbUser ) ) return unauthorized ( ex ) ;
if ( ! dbUser . permissions ( ) . contains ( PERMISSION . CREATE_USERS ) ) return forbidden ( ex ) ;
var json = json ( ex ) ;
if ( json . has ( USER ) ) json = json . getJSONObject ( USER ) ;
@ -511,11 +480,11 @@ public class UserModule extends BaseHandler {
@@ -511,11 +480,11 @@ public class UserModule extends BaseHandler {
} catch ( UmbrellaException e ) {
return send ( ex , e ) ;
}
return sendEmptyResponse ( HTTP_OK , ex ) ;
return ok ( ex ) ;
}
private boolean patchService ( HttpExchange ex , String serviceName , UmbrellaUser requestingUser ) throws IOException {
if ( ! ( requestingUser instanceof DbUser user & & user . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return sendEmptyResponse ( HTTP_FORBIDDEN , ex ) ;
if ( ! ( requestingUser instanceof DbUser user & & user . permissions ( ) . contains ( MANAGE_LOGIN_SERVICES ) ) ) return forbidden ( ex ) ;
try {
var json = json ( ex ) ;
if ( ! json . has ( NAME ) | | ! ( json . get ( NAME ) instanceof String name ) | | name . isBlank ( ) ) return sendContent ( ex , HTTP_UNPROCESSABLE , format ( ERROR_MISSING_FIELD , NAME ) ) ;