diff --git a/self-services/pom.xml b/self-services/pom.xml index c7a5d53..432eb3d 100644 --- a/self-services/pom.xml +++ b/self-services/pom.xml @@ -38,6 +38,17 @@ protobuf-java provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + diff --git a/self-services/src/main/java/jp/openstandia/midpoint/grpc/SelfServiceResource.java b/self-services/src/main/java/jp/openstandia/midpoint/grpc/SelfServiceResource.java index d081690..adf27bc 100644 --- a/self-services/src/main/java/jp/openstandia/midpoint/grpc/SelfServiceResource.java +++ b/self-services/src/main/java/jp/openstandia/midpoint/grpc/SelfServiceResource.java @@ -17,6 +17,7 @@ import com.evolveum.midpoint.prism.delta.builder.S_ItemEntry; import com.evolveum.midpoint.prism.delta.builder.S_MaybeDelete; import com.evolveum.midpoint.prism.delta.builder.S_ValuesEntry; +import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.ObjectQuery; @@ -24,6 +25,9 @@ import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.LocalizableMessage; +import com.evolveum.midpoint.util.LocalizableMessageList; +import com.evolveum.midpoint.util.SingleLocalizableMessage; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; @@ -33,8 +37,10 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; +import io.grpc.Metadata; import io.grpc.Status; import io.grpc.StatusRuntimeException; +import io.grpc.protobuf.ProtoUtils; import io.grpc.stub.StreamObserver; import org.lognet.springboot.grpc.GRpcService; import org.springframework.beans.factory.annotation.Autowired; @@ -72,6 +78,18 @@ public class SelfServiceResource extends SelfServiceResourceGrpc.SelfServiceReso @Autowired protected transient AuthenticationEvaluator passwordAuthenticationEvaluator; + @Override + public Metadata handlePolicyViolationException(PolicyViolationException e) { + PolicyError error = TypeConverter.toPolicyError(e); + Metadata metadata = new Metadata(); + + Metadata.Key POLICY_ERROR_KEY = + ProtoUtils.keyForProto(PolicyError.getDefaultInstance()); + metadata.put(POLICY_ERROR_KEY, error); + + return metadata; + } + @Override public void modifyProfile(ModifyProfileRequest request, StreamObserver responseObserver) { LOGGER.debug("Start modifyProfile"); @@ -89,41 +107,24 @@ public void modifyProfile(ModifyProfileRequest request, StreamObserver responseObserver) { LOGGER.debug("Start updateCredential"); @@ -205,7 +203,6 @@ public void forceUpdateCredential(ForceUpdateCredentialRequest request, StreamOb public void requestRole(RequestRoleRequest request, StreamObserver responseObserver) { LOGGER.debug("Start requestRole"); - LOGGER.debug("End requestRole"); } @@ -256,7 +253,10 @@ protected void updateCredential(MidPointTaskContext ctx, String oldCred, String modelService.executeChanges(deltas, null, task, updateResult); updateResult.computeStatus(); - } catch (EncryptionException | ObjectAlreadyExistsException | PolicyViolationException e) { + } catch (PolicyViolationException e) { + LoggingUtils.logExceptionAsWarning(LOGGER, "Couldn't save password changes because of policy violation: {}", e, e.getMessage()); + throw e; + } catch (EncryptionException | ObjectAlreadyExistsException e) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't save password changes", e); throw e; } finally { diff --git a/self-services/src/main/java/jp/openstandia/midpoint/grpc/TypeConverter.java b/self-services/src/main/java/jp/openstandia/midpoint/grpc/TypeConverter.java new file mode 100644 index 0000000..d7c5d31 --- /dev/null +++ b/self-services/src/main/java/jp/openstandia/midpoint/grpc/TypeConverter.java @@ -0,0 +1,172 @@ +package jp.openstandia.midpoint.grpc; + +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.util.LocalizableMessage; +import com.evolveum.midpoint.util.LocalizableMessageList; +import com.evolveum.midpoint.util.SingleLocalizableMessage; +import com.evolveum.midpoint.util.exception.PolicyViolationException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +import javax.xml.bind.annotation.XmlElement; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.*; +import java.util.stream.Collectors; + +public class TypeConverter { + + private static Map userTypeMap = new HashMap<>(); + private static Map userValueTypeMap = new HashMap<>(); + + static { + Map strToItemName = new HashMap<>(); + + Field[] fields = UserType.class.getFields(); + Arrays.stream(fields) + .filter(x -> x.getName().startsWith("F_") && x.getType() == ItemName.class) + .forEach(x -> { + String name = x.getName(); + try { + UserItemPath path = UserItemPath.valueOf(name); + ItemName itemName = (ItemName) x.get(null); + userTypeMap.put(path, itemName); + strToItemName.put(itemName.getLocalPart(), itemName); + } catch (IllegalArgumentException | IllegalAccessException ignore) { + } + }); + + Method[] methods = UserType.class.getMethods(); + Arrays.stream(methods) + .filter(x -> x.isAnnotationPresent(XmlElement.class)) + .forEach(x -> { + XmlElement ele = x.getAnnotation(XmlElement.class); + + ItemName itemName = strToItemName.get(ele.name()); + if (itemName == null) { + return; + } + Class returnType = x.getReturnType(); + + if (returnType.isAssignableFrom(List.class)) { + Type genericReturnType = x.getGenericReturnType(); + String typeName = genericReturnType.getTypeName(); + if (typeName.contains(String.class.getName())) { + userValueTypeMap.put(itemName, String.class); + } else if (typeName.contains(PolyStringType.class.getName())) { + userValueTypeMap.put(itemName, PolyStringType.class); + } else { + throw new UnsupportedOperationException(itemName + " is not supported"); + } + } else { + userValueTypeMap.put(itemName, returnType); + } + }); + } + + public static ItemName toItemName(UserItemPath path) { + ItemName itemName = userTypeMap.get(path); + if (itemName == null) { + throw new UnsupportedOperationException(path + " is not supported"); + } + return itemName; + } + + public static Object toValue(UserItemPath path, String value) { + ItemName itemName = toItemName(path); + + Class clazz = userValueTypeMap.get(itemName); + + if (clazz.isAssignableFrom(String.class)) { + return value; + } + if (clazz.isAssignableFrom(PolyStringType.class)) { + return PolyString.fromOrig((String) value); + } + + throw new UnsupportedOperationException(path + " is not supported"); + } + + public static PolicyError toPolicyError(PolicyViolationException e) { + PolicyError.Builder builder = PolicyError.newBuilder(); + MessageWrapper wrapper = null; + + LocalizableMessage msg = e.getUserFriendlyMessage(); + if (msg instanceof SingleLocalizableMessage) { + wrapper = toMessageWrapper((SingleLocalizableMessage) msg); + + } else if (msg instanceof LocalizableMessageList) { + wrapper = toMessageWrapper((LocalizableMessageList) msg); + } + + if (wrapper == null) { + throw new UnsupportedOperationException(msg.getClass() + " is not supported"); + } + + builder.addErrors(wrapper); + + return builder.build(); + } + + private static MessageWrapper toMessageWrapper(LocalizableMessageList list) { + MessageList messageList = toMessageList(list); + return MessageWrapper.newBuilder() + .setMsgListArg(messageList) + .build(); + } + + private static MessageList toMessageList(LocalizableMessageList list) { + MessageList.Builder builder = MessageList.newBuilder(); + + for (LocalizableMessage msg : list.getMessages()) { + MessageWrapper wrapper = null; + if (msg instanceof SingleLocalizableMessage) { + wrapper = toMessageWrapper((SingleLocalizableMessage) msg); + + } else if (msg instanceof LocalizableMessageList) { + wrapper = toMessageWrapper((LocalizableMessageList) msg); + } + + builder.addArgs(wrapper); + } + + return builder.build(); + } + + private static MessageWrapper toMessageWrapper(SingleLocalizableMessage msg) { + return MessageWrapper.newBuilder() + .setMsgArg(toMessage(msg)) + .build(); + } + + private static Message toMessage(SingleLocalizableMessage msg) { + return Message.newBuilder() + .setKey(msg.getKey()) + .addAllArgs(toMessageWrappers(msg.getArgs())) + .build(); + } + + private static Iterable toMessageWrappers(Object[] args) { + List list = new ArrayList<>(); + + for (Object arg : args) { + MessageWrapper wrapper; + + if (arg instanceof SingleLocalizableMessage) { + wrapper = toMessageWrapper((SingleLocalizableMessage) arg); + } else if (arg instanceof LocalizableMessageList) { + wrapper = toMessageWrapper((LocalizableMessageList) arg); + } else { + wrapper = MessageWrapper.newBuilder() + .setStringArg(arg != null ? arg.toString() : "") + .build(); + } + + list.add(wrapper); + } + + return list; + } +} \ No newline at end of file diff --git a/self-services/src/main/proto/SelfResource.proto b/self-services/src/main/proto/SelfResource.proto index 27873e2..4af6c16 100644 --- a/self-services/src/main/proto/SelfResource.proto +++ b/self-services/src/main/proto/SelfResource.proto @@ -14,11 +14,6 @@ service SelfServiceResource { */ rpc modifyProfile(ModifyProfileRequest) returns (ModifyProfileResponse); - /** - * Update user profile. - */ - rpc updateProfile(UpdateProfileRequest) returns (UpdateProfileResponse); - /** * Update credential with current password validating. */ @@ -47,26 +42,35 @@ message UserItemDelta { } enum UserItemPath { - NAME = 0; - FULL_NAME = 1; - GIVEN_NAME = 2; - FAMILY_NAME = 3; - ADDITIONAL_NAME = 4; - NICK_NAME = 5; - HONORIFIC_PREFIX = 6; - HONORIFIC_SUFFIX = 7; - TITLE = 8; - PREFERRED_LANGUAGE = 9; - LOCALE = 10; - TIMEZONE = 11; - EMAIL_ADDRESS = 12; - TELEPHONE_NUMBER = 13; - EMPLOYEE_NUMBER = 14; - EMPLOYEE_TYPE = 15; - COST_CENTER = 16; - ORGANIZATION = 17; - ORGANIZATIONAL_UNIT = 18; - LOCALITY = 19; + // ObjectType + F_NAME = 0; + F_DESCRIPTION = 1; + F_SUBTYPE = 2; + F_LIFECYCLE_STATE = 3; + + // FocusType + F_JPEG_PHOTO = 20; + F_COST_CENTER = 21; + F_LOCALITY = 22; + F_PREFERRED_LANGUAGE = 23; + F_LOCALE = 24; + F_TIMEZONE = 25; + F_EMAIL_ADDRESS = 26; + F_TELEPHONE_NUMBER = 27; + + // UserType + F_FULL_NAME = 40; + F_GIVEN_NAME = 41; + F_FAMILY_NAME = 42; + F_ADDITIONAL_NAME = 43; + F_NICK_NAME = 44; + F_HONORIFIC_PREFIX = 45; + F_HONORIFIC_SUFFIX = 46; + F_TITLE = 47; + F_EMPLOYEE_NUMBER = 48; + F_EMPLOYEE_TYPE = 49; + F_ORGANIZATION = 50; + F_ORGANIZATIONAL_UNIT = 51; } message ModifyProfileResponse { @@ -154,3 +158,24 @@ message AssignOption { message RequestRoleResponse { } + +message Message { + string key = 1; + repeated MessageWrapper args = 2; +} + +message MessageWrapper { + oneof arg { + Message msgArg = 3; + MessageList msgListArg = 4; + string stringArg = 5; + } +} + +message MessageList { + repeated MessageWrapper args = 1; +} + +message PolicyError { + repeated MessageWrapper errors = 1; +} \ No newline at end of file diff --git a/self-services/src/test/java/TestBasicAuthClient.java b/self-services/src/test/java/TestBasicAuthClient.java index 4a80d36..07f358e 100644 --- a/self-services/src/test/java/TestBasicAuthClient.java +++ b/self-services/src/test/java/TestBasicAuthClient.java @@ -26,7 +26,7 @@ public static void main(String[] args) throws UnsupportedEncodingException { ModifyProfileRequest request = ModifyProfileRequest.newBuilder() .addModifications( UserItemDelta.newBuilder() - .setName(UserItemPath.FAMILY_NAME) + .setName(UserItemPath.F_FAMILY_NAME) .setValuesToReplace("Foo") .build() ) diff --git a/self-services/src/test/java/TestJWTAuthClient.java b/self-services/src/test/java/TestJWTAuthClient.java index ef594e5..1f58c6d 100644 --- a/self-services/src/test/java/TestJWTAuthClient.java +++ b/self-services/src/test/java/TestJWTAuthClient.java @@ -37,7 +37,7 @@ public static void main(String[] args) throws UnsupportedEncodingException { ModifyProfileRequest request = ModifyProfileRequest.newBuilder() .addModifications( UserItemDelta.newBuilder() - .setName(UserItemPath.FAMILY_NAME) + .setName(UserItemPath.F_FAMILY_NAME) .setValuesToReplace("Bar") .build() ) diff --git a/self-services/src/test/java/jp/openstandia/midpoint/grpc/MidPointGrpcTestRunner.java b/self-services/src/test/java/jp/openstandia/midpoint/grpc/MidPointGrpcTestRunner.java new file mode 100644 index 0000000..b9f5874 --- /dev/null +++ b/self-services/src/test/java/jp/openstandia/midpoint/grpc/MidPointGrpcTestRunner.java @@ -0,0 +1,34 @@ +package jp.openstandia.midpoint.grpc; + +import com.evolveum.midpoint.web.boot.MidPointSpringApplication; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.util.FileSystemUtils; + +import java.io.File; + +public class MidPointGrpcTestRunner implements BeforeAllCallback, AfterAllCallback { + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + FileSystemUtils.deleteRecursively(new File("./target/midpoint")); + + setProperites(); + + MidPointSpringApplication.main(new String[]{}); + } + + @Override + public void afterAll(ExtensionContext extensionContext) throws Exception { + setProperites(); + + MidPointSpringApplication.main(new String[]{"stop"}); + } + + public void setProperites() { + System.setProperty("file.encoding", "UTF-8"); + System.setProperty("midpoint.home", "./target/midpoint"); + System.setProperty("midpoint.logging.alt.enabled", "true"); + } +} diff --git a/self-services/src/test/java/jp/openstandia/midpoint/grpc/SelfServiceResourceITest.java b/self-services/src/test/java/jp/openstandia/midpoint/grpc/SelfServiceResourceITest.java new file mode 100644 index 0000000..f1014e9 --- /dev/null +++ b/self-services/src/test/java/jp/openstandia/midpoint/grpc/SelfServiceResourceITest.java @@ -0,0 +1,216 @@ +package jp.openstandia.midpoint.grpc; + +import com.google.protobuf.Descriptors; +import io.grpc.*; +import io.grpc.protobuf.ProtoUtils; +import io.grpc.stub.MetadataUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.UnsupportedEncodingException; +import java.util.Base64; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MidPointGrpcTestRunner.class) +class SelfServiceResourceITest { + static ManagedChannel channel; + + @BeforeAll + static void init() { + channel = ManagedChannelBuilder.forAddress("localhost", 6565) + .usePlaintext() + .build(); + } + + @AfterAll + static void cleanup() { + channel.shutdownNow(); + } + + @Test + void modifyProfile() throws Exception { + SelfServiceResourceGrpc.SelfServiceResourceBlockingStub stub = SelfServiceResourceGrpc.newBlockingStub(channel); + + String token = Base64.getEncoder().encodeToString("Administrator:5ecr3t".getBytes("UTF-8")); + + Metadata headers = new Metadata(); + headers.put(Constant.AuthorizationMetadataKey, "Basic " + token); +// headers.put(Constant.SwitchToPrincipalByNameMetadataKey, "test"); + + stub = MetadataUtils.attachHeaders(stub, headers); + + ModifyProfileRequest request = ModifyProfileRequest.newBuilder() + .addModifications( + UserItemDelta.newBuilder() + .setName(UserItemPath.F_FAMILY_NAME) + .setValuesToReplace("Foo") + .build() + ) + .build(); + + stub.modifyProfile(request); + } + + @Test + void updateCredential() throws Exception { + SelfServiceResourceGrpc.SelfServiceResourceBlockingStub stub = SelfServiceResourceGrpc.newBlockingStub(channel); + + String token = Base64.getEncoder().encodeToString("Administrator:5ecr3t".getBytes("UTF-8")); + + Metadata headers = new Metadata(); + headers.put(Constant.AuthorizationMetadataKey, "Basic " + token); + + stub = MetadataUtils.attachHeaders(stub, headers); + + UpdateCredentialRequest request = UpdateCredentialRequest.newBuilder() + .setOld("5ecr3t") + .setNew("password") + .build(); + + stub.updateCredential(request); + + // Update authorization header with new password + token = Base64.getEncoder().encodeToString("Administrator:password".getBytes("UTF-8")); + headers.put(Constant.AuthorizationMetadataKey, "Basic " + token); + stub = MetadataUtils.attachHeaders(stub, headers); + + // Back to original password by forceUpdateCredential + ForceUpdateCredentialRequest forceReq = ForceUpdateCredentialRequest.newBuilder() + .setNew("5ecr3t") + .build(); + + stub.forceUpdateCredential(forceReq); + } + + @Test + void passwordPolicyErrorWithSingleError() throws Exception { + SelfServiceResourceGrpc.SelfServiceResourceBlockingStub stub = SelfServiceResourceGrpc.newBlockingStub(channel); + + String token = Base64.getEncoder().encodeToString("Administrator:5ecr3t".getBytes("UTF-8")); + + Metadata headers = new Metadata(); + headers.put(Constant.AuthorizationMetadataKey, "Basic " + token); + + stub = MetadataUtils.attachHeaders(stub, headers); + + UpdateCredentialRequest request = UpdateCredentialRequest.newBuilder() + .setOld("5ecr3t") + .setNew("123") + .build(); + + try { + stub.updateCredential(request); + fail("Should be thrown Exception of password policy error"); + } catch (StatusRuntimeException e) { + assertEquals(Status.Code.INVALID_ARGUMENT, e.getStatus().getCode()); + + Metadata.Key POLICY_ERROR = + ProtoUtils.keyForProto(PolicyError.getDefaultInstance()); + + PolicyError policyError = e.getTrailers().get(POLICY_ERROR); + + List errorsList = policyError.getErrorsList(); + assertEquals(1, errorsList.size()); + + MessageWrapper wrapper = errorsList.get(0); + assertTrue(wrapper.hasMsgArg()); + + Message msg = wrapper.getMsgArg(); + String errKey = msg.getKey(); + assertEquals("PolicyViolationException.message.credentials.password", errKey); + + List argsList = msg.getArgsList(); + assertEquals(1, argsList.size()); + + MessageWrapper argsWrapper = argsList.get(0); + assertTrue(argsWrapper.hasMsgArg()); + + Message subMsgArgs = argsWrapper.getMsgArg(); + String subErrKey = subMsgArgs.getKey(); + assertEquals("ValuePolicy.minimalSizeNotMet", subErrKey); + + List subMsgArgsList = subMsgArgs.getArgsList(); + assertEquals(2, subMsgArgsList.size()); + + MessageWrapper subMsgArg1 = subMsgArgsList.get(0); + assertFalse(subMsgArg1.hasMsgArg()); + assertFalse(subMsgArg1.hasMsgListArg()); + assertEquals("5", subMsgArg1.getStringArg()); + + MessageWrapper subMsgArg2= subMsgArgsList.get(1); + assertFalse(subMsgArg2.hasMsgArg()); + assertFalse(subMsgArg2.hasMsgListArg()); + assertEquals("3", subMsgArg2.getStringArg()); + } + } + + @Test + void passwordPolicyErrorWithMultipleError() throws Exception { + SelfServiceResourceGrpc.SelfServiceResourceBlockingStub stub = SelfServiceResourceGrpc.newBlockingStub(channel); + + String token = Base64.getEncoder().encodeToString("Administrator:5ecr3t".getBytes("UTF-8")); + + Metadata headers = new Metadata(); + headers.put(Constant.AuthorizationMetadataKey, "Basic " + token); + + stub = MetadataUtils.attachHeaders(stub, headers); + + UpdateCredentialRequest request = UpdateCredentialRequest.newBuilder() + .setOld("5ecr3t") + .setNew("1111") + .build(); + + try { + stub.updateCredential(request); + fail("Should be thrown Exception of password policy error"); + } catch (StatusRuntimeException e) { + assertEquals(Status.Code.INVALID_ARGUMENT, e.getStatus().getCode()); + + Metadata.Key POLICY_ERROR = + ProtoUtils.keyForProto(PolicyError.getDefaultInstance()); + + PolicyError policyError = e.getTrailers().get(POLICY_ERROR); + + List errorsList = policyError.getErrorsList(); + assertEquals(1, errorsList.size()); + + MessageWrapper wrapper = errorsList.get(0); + assertTrue(wrapper.hasMsgArg()); + + Message msg = wrapper.getMsgArg(); + String errKey = msg.getKey(); + assertEquals("PolicyViolationException.message.credentials.password", errKey); + + List argsList = msg.getArgsList(); + assertEquals(1, argsList.size()); + + MessageWrapper argsWrapper = argsList.get(0); + assertFalse(argsWrapper.hasMsgArg(), "Should have multiple errors"); + assertTrue(argsWrapper.hasMsgListArg(), "Should have multiple errors"); + + MessageList msgListArg = argsWrapper.getMsgListArg(); + List subMsgList = msgListArg.getArgsList(); + assertEquals(2, subMsgList.size(), "Should have multiple errors"); + + MessageWrapper argsWrapper1 = subMsgList.get(0); + + Message subMsg1Args = argsWrapper1.getMsgArg(); + String subErr1Key = subMsg1Args.getKey(); + assertEquals("ValuePolicy.minimalSizeNotMet", subErr1Key); + + MessageWrapper argsWrapper2 = subMsgList.get(1); + + Message subMsg2Args = argsWrapper2.getMsgArg(); + String subErr2Key = subMsg2Args.getKey(); + assertEquals("ValuePolicy.minimalUniqueCharactersNotMet", subErr2Key); + } + } + + @Test + void requestRole() { + } +} \ No newline at end of file diff --git a/self-services/src/test/java/jp/openstandia/midpoint/grpc/TypeConverterTest.java b/self-services/src/test/java/jp/openstandia/midpoint/grpc/TypeConverterTest.java new file mode 100644 index 0000000..1d8cb71 --- /dev/null +++ b/self-services/src/test/java/jp/openstandia/midpoint/grpc/TypeConverterTest.java @@ -0,0 +1,35 @@ +package jp.openstandia.midpoint.grpc; + +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class TypeConverterTest { + + @Test + public void toItemName() { + ItemName name = TypeConverter.toItemName(UserItemPath.F_NAME); + assertEquals(UserType.F_NAME, name, "Should get ItemName of ObjectType"); + + ItemName locality = TypeConverter.toItemName(UserItemPath.F_LOCALITY); + assertEquals(UserType.F_LOCALITY, locality, "Should get ItemName of FocusType"); + + ItemName fullName = TypeConverter.toItemName(UserItemPath.F_FULL_NAME); + assertEquals(UserType.F_FULL_NAME, fullName, "Should get ItemName of UserType"); + } + + @Test + public void toValue() { + Object foo = TypeConverter.toValue(UserItemPath.F_NAME, "foo"); + assertEquals(PolyString.class, foo.getClass()); + + Object bar = TypeConverter.toValue(UserItemPath.F_EMPLOYEE_TYPE, "bar"); + assertEquals(String.class, bar.getClass()); + + Object hoge = TypeConverter.toValue(UserItemPath.F_ORGANIZATION, "hoge"); + assertEquals(PolyString.class, hoge.getClass()); + } +} \ No newline at end of file diff --git a/server/src/main/java/jp/openstandia/midpoint/grpc/MidPointGrpcService.java b/server/src/main/java/jp/openstandia/midpoint/grpc/MidPointGrpcService.java index b525728..4bedf44 100644 --- a/server/src/main/java/jp/openstandia/midpoint/grpc/MidPointGrpcService.java +++ b/server/src/main/java/jp/openstandia/midpoint/grpc/MidPointGrpcService.java @@ -4,13 +4,17 @@ import com.evolveum.midpoint.security.api.HttpConnectionInformation; import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.LocalizableMessage; import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.SingleLocalizableMessage; import com.evolveum.midpoint.util.exception.AuthorizationException; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.PolicyViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.lowagie.text.Meta; +import io.grpc.Metadata; import io.grpc.Status; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -47,10 +51,12 @@ default T runTask(MidPointTask task) { .withCause(e) .asRuntimeException(); } catch (PolicyViolationException e) { + Metadata metadata = handlePolicyViolationException(e); + throw Status.INVALID_ARGUMENT .withDescription(e.getErrorTypeMessage()) .withCause(e) - .asRuntimeException(); + .asRuntimeException(metadata); } catch (AuthorizationException e) { throw Status.PERMISSION_DENIED .withDescription(e.getErrorTypeMessage()) @@ -70,4 +76,9 @@ default T runTask(MidPointTask task) { SecurityContextHolder.getContext().setAuthentication(null); } } + + default Metadata handlePolicyViolationException(PolicyViolationException e) { + return new Metadata(); + } } + diff --git a/server/src/main/proto/UserResource.proto b/server/src/main/proto/UserResource.proto deleted file mode 100644 index 1c7ddf2..0000000 --- a/server/src/main/proto/UserResource.proto +++ /dev/null @@ -1,69 +0,0 @@ -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "jp.openstandia.midpoint.grpc"; - -package midpoint; - -/** - * Provide services for an UserType resource. - */ -service UserResourceService { - /** - * Update credential with current password validating. - */ - rpc updateCredentialByName(UpdateCredentialByNameRequest) returns (UpdateCredentialResponse); - - /** - * Force update credential. - */ - rpc forceUpdateCredentialByName(ForceUpdateCredentialByNameRequest) returns (UpdateCredentialResponse); - - /** - * Request role. - */ - rpc requestRoleByName(RequestRoleByNameRequest) returns (RequestRoleResponse); -} - -message UpdateCredentialByNameRequest { - // Name of target user. - string name = 1; - // Current credential. - string old = 2; - // New credential. - string new = 3; -} - -message ForceUpdateCredentialByNameRequest { - // Name of target user. - string name = 1; - // New credential. - string new = 3; -} - -message UpdateCredentialResponse { -} - -message RequestRoleByNameRequest { - // Name of initiator. - string name = 1; - // Assign requests. - repeated AssignRequest assignRequest = 2; -} - -message AssignRequest { - // Oid of target user. - string assignTargetOid = 1; - // Oid of request role/organization/service. - string requestObjectOid = 2; - // Assign option - AssignOption option = 3; -} - -message AssignOption { - // Oid of organization reference. - string orgRef = 1; -} - -message RequestRoleResponse { -}