Implementing Search User Feature for Admins

The users tab of admin panel of SUSI.AI provides a list of all users registered on SUSI. This helps admins to get an overview of users and also provides the admins option like change user roles and delete accounts. The list of users is displayed in a table which also uses pagination to handle larger number of users. But to find a particular user can be a difficult task if the user base is large. Therefore a feature to search for users by their email has been implement which searches for users on SUSI server and then sends the searched users to the client. In this post we will discuss both about the server and client side implementation of this feature. (more…)

Continue ReadingImplementing Search User Feature for Admins

Implementing User Stats for SUSI.AI Admin Panel

SUSI.AI has an admin panel where users with roles operator or above get an overview of various stats and manage other users and skills. The admin panel allows the system admins to get a list of all users registered on susi and also provide an option to change their user roles as well. The admin tab provides us with the statistics of its users. In this post we will discuss how this is implemented on susi server. (more…)

Continue ReadingImplementing User Stats for SUSI.AI Admin Panel

How to Change a Password and Forgot Password Feature in the SUSI.AI Server

The accounting system of SUSI.AI provides its users the option to change the password of their accounts. This features gives us two options, either we can change our password by entering the older password or if the user forgot the password, they are provided a link on their email address through which we can change our password. Using either option, the user has to authenticate themselves before they can actually change their passwords. If the user has the current password, it is considered as a parameter of authentication. In other case the user has to check their email account for the link which also confirms the authenticity of user. In this post we will discuss how both options works on SUSI. (more…)

Continue ReadingHow to Change a Password and Forgot Password Feature in the SUSI.AI Server

Delete User Account Service using LoginService.java API in SUSI.AI

SUSI.AI has an api to handle all account related services called accounts.susi.ai. This API provides services like change password and delete account. the main goal of accounts.susi.ai is to centralise the accounts’ related settings from web, android and iOS clients into a single place like other accounting services. In this post we will discuss one of these features which is the delete user account from SUSI.AI.

The api accounts.susi.ai has a react file DeleteAccount.react.js. This file handle the delete account service and interacts with the LoginServce.java api, which is the core file for authentication. I will discuss in details how these two interact with each other and with other files. (more…)

Continue ReadingDelete User Account Service using LoginService.java API in SUSI.AI

Fetching Info of All Users and their connected devices for the SUSI.AI Admin Panel

Fetching the data of all users is required for displaying the list of users on the SUSI.AI Admin panel. It was also required to fetch the information of connected devices of the user along with the other user data. The right to fetch the data of all users should only be permitted to user roles “OPERATOR” and above. This blog post explains how the data of connected devices of all users is fetched, which can then be used in the Admin panel. How is user data stored on the server? All the personal accounting information of any user is stored in the user’s accounting object. This is stored in the “accounting.json” file. The structure of this file is as follows: { "email:akjn11@gmail.com": { "devices": { "8C-39-45-23-D8-95": { "name": "Device 2", "room": "Room 2", "geolocation": { "latitude": "54.34567", "longitude": "64.34567" } } }, "lastLoginIP": "127.0.0.1" }, "email:akjn22@gmail.com": { "devices": { "1C-29-46-24-D3-55": { "name": "Device 2", "room": "Room 2", "geolocation": { "latitude": "54.34567", "longitude": "64.34567" } } }, "lastLoginIP": "127.0.0.1" } }   As can be seen from the above sample content of the “accounting.json” file, we need to fetch this data so that it can then be used to display the list of users along with their connected devices on the Admin panel. Implementing API to fetch user data and their connected devices The endpoint of the servlet is “/aaa/getUsers.json” and the minimum user role for this servlet is “OPERATOR”. This is implemented as follows: @Override public String getAPIPath() { return "/aaa/getUsers.json"; } @Override public UserRole getMinimalUserRole() { return UserRole.OPERATOR; }   Let us go over the main method serviceImpl() of the servlet: We need to traverse through the user data of all authorized users. This is done by getting the data using DAO.getAuthorizedClients() and storing them in a Collection. Then we extract all the keys from this collection, which is then used to traverse into the Collection and fetch the user data. The implementation is as follows: Collection<ClientIdentity> authorized = DAO.getAuthorizedClients(); List<String> keysList = new ArrayList<String>(); authorized.forEach(client -> keysList.add(client.toString())); for (Client client : authorized) { // code }   Then we traverse through each client and generate a client identity to get the user role of the client. This is done using the DAO.getAuthorization() method. The user role of the client is also put in the final object which we want to return. This is implemented as follows: JSONObject json = client.toJSON(); ClientIdentity identity = new ClientIdentity(ClientIdentity.Type.email, client.getName()); Authorization authorization = DAO.getAuthorization(identity); UserRole userRole = authorization.getUserRole(); json.put("userRole", userRole.toString().toLowerCase());   Then the client credentials are generated and it is checked whether the user is verified or not. If the user is verified, then in the final object, “confirmed” is set to true, else it is set to false. ClientCredential clientCredential = new ClientCredential (ClientCredential.Type.passwd_login, identity.getName()); Authentication authentication = DAO.getAuthentication(clientCredential); json.put("confirmed", authentication.getBoolean("activated", false));   Then we fetch the accounting object of the user using DAO.getAccounting(), and extract all the user data and put them in separate key value pairs in the final…

Continue ReadingFetching Info of All Users and their connected devices for the SUSI.AI Admin Panel

How to integrate SUSI.AI with Google Sign In API

Google Sign-In manages the OAuth 2.0 flow and token lifecycle, simplifying our integration with Google APIs. A user always has the option to revoke access to an application at any time. Users can see a list of all the apps which they have given permission to access their account details and are using the login API. In this blog post I will discuss how to integrate this API with susi server API to enhance our AAA system. More on Google API here. (more…)

Continue ReadingHow to integrate SUSI.AI with Google Sign In API

Using SUSI.AI Accounting Model to store Device information on Server

Just like with Google Home devices and Amazon Alexa devices, SUSI.AI Users should have a way to add and store the information of their devices (Smart Speakers) on SUSI Server, so that it could be displayed to them on various clients. Hence, we needed a Servlet which could add and store the User data on the Server. Implementation of Servlets in SUSI.AI All servlets in SUSI extend AbstractAPIHandler class and implement APIHandler. All servlets have 4 methods, which we overwrite depending on what we want the servlet to do. They are as follows : @Override public String getAPIPath() { return null; } @Override public BaseUserRole getMinimalBaseUserRole() { return null; } @Override public JSONObject getDefaultPermissions(BaseUserRole baseUserRole) { return null; } @Override public ServiceResponse serviceImpl(Query post, HttpServletResponse response, Authorization rights, JsonObjectWithDefault permissions) throws APIException { Return null; }   How these 4 methods work together? First method is getAPIPath(). It returns the endpoint of the servlet. The second method is getMinimalBaseUserRole(). It returns the minimum privilege level required to access the endpoint. The third method is getDefaultPermissions(). It gets the Default Permissions of a UserRole in SUSI Server. Different UserRoles have different permissions defined in SUSI Server. Whenever the endpoint defined in the getAPIPath() method is called properly, it responds with whatever is defined in the fourth method, which is serviceImpl(). How is User data stored on SUSI Server? Before we move on to the actual implementation of the API required to store the device information, we should get a brief idea of how exactly User data is stored on SUSI Server. Every SUSI User has an Accounting Object. It is a JSONObject which stores the Settings of the particular User on the Server. For example, every time you change some setting on the Web Client https://chat.susi.ai, an API call is made to aaa/changeUserSettings.json with appropriate parameters with information of the changed setting, and the User settings are stored to the Server in the Accounting Object of the User. Implementation of a Servlet to store Device information on Server The task of this servlet is to store the information of a new device (Smart speaker) whenever it is initially set up using the Android/iOS app. This is the implementation of the 4 methods of a servlet which is used to store information of connected devices: @Override public String getAPIPath() { return "/aaa/addNewDevice.json"; } @Override public UserRole getMinimalUserRole() { return UserRole.USER; } @Override public JSONObject getDefaultPermissions(UserRole baseUserRole) { return null; } @Override public ServiceResponse serviceImpl(Query query, HttpServletResponse response, Authorization authorization, JsonObjectWithDefault permissions) throws APIException { JSONObject value = new JSONObject(); String key = query.get("macid", null); String name = query.get("name", null); String device = query.get("device", null); if (key == null || name == null || device == null) { throw new APIException(400, "Bad service call, missing arguments"); } else { value.put(name, device); } if (authorization.getIdentity() == null) { throw new APIException(400, "Specified user data not found, ensure you are logged in"); } else { Accounting accounting = DAO.getAccounting(authorization.getIdentity()); if (accounting.getJSON().has("devices")) { accounting.getJSON().getJSONObject("devices").put(key, value); }…

Continue ReadingUsing SUSI.AI Accounting Model to store Device information on Server

Store User’s Personal Information with SUSI

In this blog, I discuss how SUSI.AI stores personal information of it’s users. This personal information is mostly about usernames/links to different websites like LinkedIn, GitHub, Facebook, Google/Gmail etc. To store such details, we have a dedicated API. Endpoint is : https://api.susi.ai/aaa/storePersonalInfo.json In this API/Servlet, storing the details and getting the details, both the aspects are covered. At the time of making the API call, user has an option either to ask the server for a list of available store names along with their values or request the server to store the value for a particular store name. If a store name already exists and a client makes a call with new/updated value, The servlet will update the value for that particular store name. The reason you are looking at minimal user role as USER is quite obvious, i.e. these details correspond to a particular user. Hence neither we want someone writing such information anonymously nor we want this information to be visible to anonymous user until allowed by the user. In the next steps, we start evaluating the API call made by the client. We look at the combination of the parameters present in the request. If the request is to fetch list of available stores, server first checks if Accounting object even has a JSONObject for “stores” or not. If not found, it sends an error message “No personal information is added yet.” and error code 420. Prior to all these steps, server first generates an accounting object for the user. If found, details are encoded as JSONObject’s parameter. Look at the code below to understand things fairly. Accounting accounting = DAO.getAccounting(authorization.getIdentity()); if(post.get("fetchDetails", false)) { if(accounting.getJSON().has("stores")){ JSONObject jsonObject = accounting.getJSON().getJSONObject("stores"); json.put("stores", jsonObject); json.put("accepted", true); json.put("message", "details fetched successfully."); return new ServiceResponse(json); } else { throw new APIException(420, "No personal information is added yet."); } } If the request was not to fetch the list of available stores, It means client wants server to save a new field or update a previous value for that of a store name. A combination of If-else evaluates whether the call even contains required parameters. if (post.get("storeName", null) == null) { throw new APIException(422, "Bad store name encountered!"); } String storeName = post.get("storeName", null); if (post.get("value", null) == null) { throw new APIException(422, "Bad store name value encountered!"); } If request contains all the required data, then store name & value are extracted as key-value pair from the request. In the next steps, since the server is expected to store list of the store names for a particular user, First the identity is gathered from the already present authorization object in “serviceImpl” method. If the server finds a “null” identity, It throws an error with error code 400 and error message “Specified User Setting not found, ensure you are logged in”. Else, server first checks if a JSONObject with key “stores” exists or not. If not, It will create an object and will put the key value pair in the new JSONObject. Otherwise…

Continue ReadingStore User’s Personal Information with SUSI