osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discussion] Fineract CN SMS & Email Notifications Project


Hey Ebenezer,
those code
First the easy question:
The services do all have code names, which we use to name the tables.
Most of them are named after Egyptian gods.  Anubis for example plays
a part in the judgement of the newly dead, and so it seemed
appropriate that the library responsible for authentication and
authorization at the service level should also be called anubis.
There's a Maat's feather in there somewhere too.

I'm glad you picked a code name for notifications too.  I bellieve it
actually makes communication about the services more precise, and it's
also fun.

Does "wada" mean anything?

Unfortunately the code links you included don't work (I'm getting
404's).  But I took a look through your repositories as they are in
github anyways.  And it seems likely that you haven't understood how
this works yet.  Which is understandable since it is complex and
poorly documented.

The current best I have available is here, but this may be confusing
because the interaction being prepared is with identity, in addition
to identity's involvement with the provisioning of permissions:
https://cwiki.apache.org/confluence/display/FINERACT/Fineract+CN+demo-server
 (In other words identity is involved in two parts of that problem
instead of just one, and that muddies the waters.)

Let me take another swing at it.  I'm currently assuming the only
function you need from customer is CustomerManager.findCustomer.  That
function is in the permittable group customer__v1__customer.  Here's
what will need to happen and how your code fits in.  I've put stars
next to the parts which will require you to do something.  I'll
explain below what you need to do for each star.  Some of it you are
already doing, so you can take those stars home : o)

demo_server -> provisioner: add customer service to the tenant
(skipping some parts here)
  provisioner -> customer: ask what permissions are part of customer
  provisioner -> identity: create the permission groups which are part
of customer, including the permittable group customer__v1__customer.
demo_server -> identity: create the role notificationAdmin, set it to
include permissions to the parts of customer you want to access. *1
demo_server -> identity: add user wadaadmin with the role notificationAdmin. *2
demo_server -> provisioner: add wada service to the tenant *3
  provisioner -> wada: provision signature with same timestamp as
current identity signature.
  provisioner -> identity: create application with signature returned by wada
  provisioner -> wada: ask what permissions wada needs.  Wada responds
that it needs customer__v1__customer. *4
  provisioner -> identity: create permission request for wada to
access customer to get customer information.
  provisioner -> wada: initialize tenant data tables in separate database. *5
demo_server -> identity: allow wada to call customer__v1__customer as
wadaadmin. *6

*1.  You are already doing this in the demo-server function
ServiceRunner::defineNotificationRole
*2.  You are already doing this in the demo-server function
ServiceRunner::createNotificationsAdmin
*3.  You are already doing this in the demo-server function
ServiceRunner::provisionAppsViaSeshat
*4.  This is done by creating a feign interface for customer within
the notification service code.  You can find an example in rhythm
under ApplicationPermissionRequestCreator, intended to make it
possible for rhythm to access identity.  In your case though you want
wada to access customer, so you'll create a class that looks something
like this:

@EndpointSet(identifier = "notificiations__v1__customer__v1")
@FeignClient(name="customer-v1", path="/customer/v1",
configuration=PermittedFeignClientsConfiguration.class)
public interface ApplicationPermissionRequestCreator {
  @RequestMapping(...) /* copy params from CustomerManager */
  @ThrowsException(...)/* copy params from CustomerManager */
  @Permittable(groupId =
org.apache.fineract.cn.customer.PermittableGroupIds.CUSTOMER)
  Customer findCustomer(...); /* copy params from CustomerManager */
}

*5.  You are already doing this in notifications function
MigrationAggregate::provisionAppsViaSeshatForTenant with a call to
provisionApp for notificationManager.
*6.  After all the other pieces are in place, login as wadaadmin and
call.  This won't work until after notificationManager is provisioned.
identityManager.api().setApplicationPermissionEnabledForUser(
        notificationManager.name(),
        org.apache.fineract.cn.customer.PermittableGroupIds.CUSTOMER,
        notificationsAdminUser.getIdentifier(),
        true);

If you still can't figure it out after this, I'd like to puzzle
together with you.  Write me an e-mail and we'll set up a pair
programming session, and then bring back anything we learn to the
list.

Best Regards,
Myrle Krantz

On Mon, Oct 8, 2018 at 12:21 AM Ebenezer Graham
<egraham15@xxxxxxxxxxxxxx> wrote:
>
> HI Myrle,
>
> I will try this approach to connect to the VM. Thanks.
>
> Yes you are right, this happens during provisioning of the services
>
> This is the line throwing the exception
> https://github.com/ebenezergraham/fineract-cn-demo-server/blob/application-permission-for-notification/
> src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java#L451
> This is where I attempt to setApplicationPermissionEnabledForUser.
>
> I attempted to create the application request here:
> https://github.com/ebenezergraham/fineract-cn-demo-server/blob/application-permission-for-notification/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java#L484-#L514
>
>
> ** at provisioning, service A tells provisioner about its
> permissiongroups.  provisioner then tells identity.*
>
> And so I understand this mechanism correctly, for the notification service
> to be able to read data from the customer service a permission group has to
> be defined in customer.
>
> Please correct me if I am wrong, this is done by declaring a groupId in the
> PermittableGroupIds interface in customer(eg:
> notification__v1__customer__v1?) and under the hood, provisioner will set
> that in identity.
>
>
> ** The demo-server than creates a user (Fred?) which which has accessto
> that permission group.*
> In other not create new users ( as this caused problems for other
> developers) I believe I can use scheduler just like rhythm?
>
> I have added permission to read from a customer during the creation of the
> scheduler
> https://github.com/ebenezergraham/fineract-cn-demo-server/blob/application-permission-for-notification/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java#L588-#L590
>
>
>
> ** Then when service B is being provisioned, it tells identity aboutthe
> permission groups that it will need in service A.*
> So I believe the start fails because notification is setting a permission
> which doesn't exist (customer never informed identity through provisioner).
>
>
> ** The demo-server, in the name of Fred, gives service B permission tocall
> service A on that permission group as Fred.*
>
> Also, I saw that other services have code names from the documentation. And
> so I gave the notification service the name wada. I used it to prefix the
> database tables. Is it alright to give it a code name? :)
>
> *At your service,*
>
> *Ebenezer Graham*
>
> *BSc (Hons) Computing*
>
>
> [image: EmailSignature.png]
>
> African Leadership University,
>
> Power Mill Road, Pamplemousses,
>
> Mauritius.
>
>
> *skype*:
> ebenezer.graham
> GitHub <https://github.com/ebenezergraham> | LinkedIn
> <https://www.linkedin.com/in/ebenezer-graham/> | Twitter
> <https://twitter.com/pactmart> | Facebook
> <https://www.facebook.com/pactmart>
> www.pactmart.com | Freelancing made easy.
>
>
> *“Talk is cheap, show me the code.” *- *Linus Torvalds*
>
>
>
>
> On Mon, 8 Oct 2018 at 01:08, Myrle Krantz <myrle@xxxxxxxxxx> wrote:
>
> > Hey Ebenezer,
> >
> > I've never debugged a process on a remote server, but it should be
> > possible.  First you'll need to find out what port debugging is
> > running on and open that port.
> >
> > Aside from that, I've included the text you linked to in pastebin
> > below (for snippets this short it's easier on me if you just include
> > them in the mail.)
> >
> > It seems like your problem is actually in the start up of demo-server,
> > is that correct?  But what line number?  What call is producing this
> > exception?
> >
> > I can explain a bit about the permission requesting mechanism in
> > identity.  If service B needs to call service A, then the following
> > happens:
> > * at provisioning, service A tells provisioner about its permission
> > groups.  provisioner then tells identity.
> > * The demo-server than creates a user (Fred?) which which has access
> > to that permission group.
> > * Then when service B is being provisioned, it tells identity about
> > the permission groups that it will need in service A.
> > * The demo-server, in the name of Fred, gives service B permission to
> > call service A on that permission group as Fred.
> >
> > This line looks like you're expecting a permission group in customer
> > called wada.  There is no such permission group.  Are you trying to
> > get information from customer?  Is that why you need this permission?
> > You'll need to call identity.setApplicationPermissionEnabledForUser.
> >
> > Can you share the code throwing this exception?  It would make things
> > much easier.
> >
> > Best Regards,
> > Myrle
> >
> >
> > 1) startDevServer(org.apache.fineract.cn.dev.ServiceRunner)
> > org.apache.fineract.cn.api.util.NotFoundException:
> > {"timestamp":1538925629122,"status":404,"error":"Not
> >
> > Found","exception":"org.apache.fineract.cn.lang.ServiceException","message":"Application
> > permission 'notification-v1.customer__v1__wada' doesn't
> >
> > exist.","path":"/identity/v1/applications/notification-v1/permissions/customer__v1__wada/users/imhotep/enabled"}
> > at
> > org.apache.fineract.cn.api.util.AnnotatedErrorDecoder.getAlternative(AnnotatedErrorDecoder.java:76)
> > at
> > org.apache.fineract.cn.api.util.AnnotatedErrorDecoder.decode(AnnotatedErrorDecoder.java:65)
> > at
> > feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138)
> > at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
> > at
> > feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
> > at com.sun.proxy.$Proxy207.setApplicationPermissionEnabledForUser(Unknown
> > Source)
> > at
> > org.apache.fineract.cn.dev.ServiceRunner.provisionAppsViaSeshatForTenant(ServiceRunner.java:451)
> > at
> > org.apache.fineract.cn.dev.ServiceRunner.provisionAppsViaSeshat(ServiceRunner.java:359)
> > at
> > org.apache.fineract.cn.dev.ServiceRunner.startDevServer(ServiceRunner.java:257)
> > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> > at
> > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> > at
> > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> > at java.lang.reflect.Method.invoke(Method.java:498)
> > at
> > org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
> > at
> > org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> > at
> > org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
> > at
> > org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> > at
> > org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> > at
> > org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
> > at
> > org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> > at
> > org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
> > at
> > org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
> > at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
> > at
> > org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
> > at
> > org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
> > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
> > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
> > at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
> > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
> > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
> > at
> > org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
> > at
> > org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
> > at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
> > at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
> > at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
> > at org.junit.rules.RunRules.evaluate(RunRules.java:20)
> > at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
> > at
> > org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
> > at org.junit.runners.Suite.runChild(Suite.java:128)
> > at org.junit.runners.Suite.runChild(Suite.java:27)
> > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
> > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
> > at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
> > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
> > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
> > at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
> > at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
> > at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
> > at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
> > at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
> > at org.apache.fineract.cn.dev.DemoServer.main(DemoServer.java:30)
> > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> > at
> > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> > at
> > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> > at java.lang.reflect.Method.invoke(Method.java:498)
> > at
> > org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
> > at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
> > at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
> > at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:58)
> >