How to enable admin to add any user to a group chat?

139 views
Skip to first unread message

Yogeswari Narayasamy

unread,
Aug 13, 2020, 11:28:43 PM8/13/20
to Tinode General
I have a requirement to create new chat groups when new users initiate chat. New users are those that don't have accounts on Tinode yet.

When a chat is initiated, an admin and the new user will be added into the newly created group. The admin will then be able to add anyone on Tinode to the group to chat with the new user.

I'd like to seek advice on the following:

1. Will admin need to be set as a root user?
2. Will I need to use gRPC to get this done?
3. How can I allow admin to add any user to the group chat? I note that a user is only able to add people he has previously chatted with into group chats. For example like the following:

Gene

unread,
Aug 14, 2020, 11:33:36 AM8/14/20
to Tinode General
I suspect you want to use Tinode for customer support. If so, I would suggest the following scheme:

1. Customer creates an account using 'anonymous' authentication scheme.
2. Customer joins and posts an initial message to write-only topic which is hard-coded in the client.
3. Your support agent sees the messages and initiates a separate group conversation with the client.

To your specific questions:

1. Will admin need to be set as a root user?

No

2. Will I need to use gRPC to get this done?

Yes. If you need automation then yes, you have to use gRPC.

3. How can I allow admin to add any user to the group chat?

The API allows group admin to add anyone to the group by user ID.

Yogeswari Narayasamy

unread,
Aug 14, 2020, 8:02:34 PM8/14/20
to Tinode General
Thank you for the guidance.

May I know how I can make grpc calls from the react client?

Is there some sample I can refer to?

I found some examples like the following to use a proxy but not sure how to go about it - for REST we'll call the endpoints, how do we do the same for grpc?

https://www.google.com/amp/s/www.freecodecamp.org/news/how-to-use-grpc-web-with-react-1c93feb691b5/amp/

Gene

unread,
Aug 14, 2020, 8:20:58 PM8/14/20
to Tinode General
Here is the documentation and examples:
React has nothing to do with grpc-web. For instance, all Tinode JS SDK functionality is in https://github.com/tinode/tinode-js which is not dependent on react at all.

Having said that I also think you are missing the point. You need gRPC for automation on the *server* side. Client side does not need gRPC.

Yogeswari Narayasamy

unread,
Aug 14, 2020, 10:01:55 PM8/14/20
to Tinode General
Apologies that I'm a bit loss and likely asking silly questions. Earlier, a senior colleague was working on this project and I'm taking over.

I understand that we have the option of using grpc with this project. The README in the server's pbx folder says:
Tinode gRPC clients must implement rpc service `Node`, Tinode plugins `Plugin`.

I open the pbx/model.proto file and the Node service definition is specified as :
service Node {
   
// Client sends a stream of ClientMsg, server responds with a stream of ServerMsg
      rpc
MessageLoop(stream ClientMsg) returns (stream ServerMsg) {}
}

I guess my question is how do I implement this bi-directional grpc service on the client side - with my client being a React app?

From my server log, I believe the gRPC server is already listening:

Gene

unread,
Aug 14, 2020, 10:39:38 PM8/14/20
to Tinode General
On Friday, August 14, 2020 at 7:01:55 PM UTC-7 Yogeswari Narayasamy wrote:
Apologies that I'm a bit loss and likely asking silly questions. Earlier, a senior colleague was working on this project and I'm taking over.

I understand that we have the option of using grpc with this project. The README in the server's pbx folder says:
Tinode gRPC clients must implement rpc service `Node`, Tinode plugins `Plugin`.

I open the pbx/model.proto file and the Node service definition is specified as :
service Node {
   
// Client sends a stream of ClientMsg, server responds with a stream of ServerMsg
      rpc
MessageLoop(stream ClientMsg) returns (stream ServerMsg) {}
}

I guess my question is how do I implement this bi-directional grpc service on the client side - with my client being a React app?


1. Let me repeat it: React has nothing to do with gRPC. React is for building UI. gRPC is for communicating with the server. 

2. I do not understand your project, but building a server-side component in React makes zero sense to me.

Yogeswari Narayasamy

unread,
Aug 14, 2020, 11:07:05 PM8/14/20
to Tinode General
>> 2. I do not understand your project, but building a server-side component in React makes zero sense to me.

Absolutely agree. :) Let me rephrase my question which I guess doesn't make sense.

Following is the code that we've written in Go that is able to create a new user group and add members to it.

We need to manually call this code everytime we want to get a new group created.
My question is how can I implement this code such that the process is automated.
For example, a user clicks 'Chat Now' on the React web app, and a new group chat is initiated and he gets to start chatting with someone.

Many thanks for all your responses, it's much appreciated.

package main
 
import (
   
"context"
   
"fmt"
   
"log"
 
   
"github.com/tinode/chat/pbx"
   
"google.golang.org/grpc"
   
"google.golang.org/grpc/credentials"
)
 
func main
() {
   crtFile
:= "/home/yogesnsamy/Coding/MHub/prod_cert/cert.crt"
   creds
, err := credentials.NewClientTLSFromFile(crtFile, "")
   
if err != nil {
       log
.Fatal("Error loading cert", err)
   
}
 
   conn
, err := grpc.Dial("dev.mhub.my:16060", grpc.WithTransportCredentials(creds))
   
if err != nil {
       log
.Fatal("Error dialing", err)
   
}
 
   c
:= pbx.NewNodeClient(conn)
   response
, err := c.MessageLoop(context.Background())
 
   
if err != nil {
       log
.Fatal("Error calling: ", err)
   
}
 
   hi
:= &pbx.ClientHi{}
   hi
.Id = "1"
   hi
.UserAgent = "Golang_Spider_Bot/3.0"
   hi
.Ver = "0.15"
   hi
.Lang = "EN"
 
   msgHi
:= &pbx.ClientMsg_Hi{Hi: hi}
   clientMessage
:= &pbx.ClientMsg{Message: msgHi}
   err
= response.Send(clientMessage)
 
   
if err != nil {
       log
.Fatal("error sending message ", err)
   
}
 
   
// LOGIN as Admin user
   
// NOTE: you will need to create an admin user account
   
// Upgrade an existing user to have admin access
   login
:= &pbx.ClientLogin{}
   login
.Id = "2"
   login
.Scheme = "basic"
   login
.Secret = []byte("alice:alice123") // normal user is also able to create a group
   clMsg
:= &pbx.ClientMsg_Login{Login: login}
   clientMessage
= &pbx.ClientMsg{Message: clMsg}
   err
= response.Send(clientMessage)
 
   
if err != nil {
       log
.Fatal("error sending message ", err)
   
}
 
   serverMsg
, err := response.Recv()
   
if err != nil {
       log
.Fatal(err)
   
}
   
// log.Println("SERVER MESSAGE 1", serverMsg)
 
   serverMsg
, err = response.Recv()
   
if err != nil {
       log
.Fatal(err)
   
}
 
   clientSub
:= &pbx.ClientSub{
       
Id:    "3",
       
Topic: "new123457",
       
SetQuery: &pbx.SetQuery{
           
Desc: &pbx.SetDesc{
               
Public: []byte(`{"fn":"BUYER GROUP"}`),
               
DefaultAcs: &pbx.DefaultAcsMode{
                   
// Auth: "N",
                   
Auth: "JRWS",
               
},
           
},
       
},
   
}
   clSub
:= &pbx.ClientMsg_Sub{Sub: clientSub}
   subMessage
:= &pbx.ClientMsg{
       
Message: clSub,
   
}
 
   err
= response.Send(subMessage)
   
if err != nil {
       log
.Fatal(err)
   
}
 
   serverMsg
, err = response.Recv()
 
   
if err != nil {
       log
.Fatal(err)
   
}
 
   code
:= serverMsg.GetCtrl().Code
 
   
if code == 200 {
       topic
:= serverMsg.GetCtrl().Topic
       clientPub
:= &pbx.ClientPub{
           
Topic:   topic, // "grpfN-i3C3zBWo",
           
Content: []byte("\"Welcome to MHub Chat!\""),
       
}
 
       clPub
:= &pbx.ClientMsg_Pub{Pub: clientPub}
       pubMessage
:= &pbx.ClientMsg{
           
Message: clPub,
           
// Note: change this to an existing user
           
// OnBehalfOf: "usrRpP-hz3gYmw", // alice
       
}
 
       err
= response.Send(pubMessage)
       
if err != nil {
           log
.Fatal(err)
       
}
 
       serverMsg
, err = response.Recv()
       
if err != nil {
           log
.Fatal(err)
       
}
       log
.Println("SERVER MESSAGE 4", serverMsg)
 
       
// usrulvFt3MUeRw // bob
       
// usr3fsC5QpNu8U  // mhub dickson
       
// usrAx7bwUjCZvw // gamuda user
       userID
:= []string{"usrulvFt3MUeRw", "usr3fsC5QpNu8U", "usrAx7bwUjCZvw"}
       
for i, s := range userID {
           fmt
.Println(s)
           clientSet
:= &pbx.ClientSet{
               
Topic: topic,
               
Query: &pbx.SetQuery{
                   
Sub: &pbx.SetSub{
                       
UserId: s,
                   
},
               
},
           
}
 
           clSet
:= &pbx.ClientMsg_Set{Set: clientSet}
           setMessage
:= &pbx.ClientMsg{
               
Message: clSet,
           
}
 
           err
= response.Send(setMessage)
           
if err != nil {
               log
.Fatal(err)
           
}
 
           serverMsg
, err = response.Recv()
           
if err != nil {
               log
.Fatal(err)
           
}
           log
.Println("SERVER MESSAGE ", i, serverMsg)
 
       
}
 
   
}
 
}


Gene

unread,
Aug 15, 2020, 1:39:00 PM8/15/20
to Tinode General
The code you shared looks strange to me:

1. Log in as an existing user Alice
2. As user Alice create a group topic "BUYER GROUP"
3. As user Alice publish "Welcome" message to the group.
4. As user Alice add three other users to the group.

I'm not sure what you are trying to achieve here.

If you just want to trigger this strange code by user action then just add a web server to your code (https://gobyexample.com/http-servers) and have the client do an HTTP GET or POST. Then call your code from there.

If you want to do it right then maybe do read and understand the message I sent earlier: https://groups.google.com/g/tinode/c/4Bg36RFzb6k/m/mNHELEPKBwAJ
Reply all
Reply to author
Forward
0 new messages