Adding feature to preview chatbot

You can access all features of SUSI.AI on chat.susi.ai. But this restricts the usage of SUSI.AI to this site only. To solve this issue, we can use a Chatbot which can be embedded on any website and then can be used by the people who visit that website, hence generalising the usage of SUSI.AI. How to embed SUSI.AI Chatbot on any website? To embed SUSI.AI Chatbot on any website, go to skills.susi.ai and login and then check out the Botbuilder section. There you can find a deploy button which will give you a code which looks something like this : <script type="text/javascript" id="susi-bot-script" data-userid="" data-group="" data-language="" data-skill="" src="https://skills.susi.ai/susi-chatbot.js" > </script>   As can be seen from the code above, it is simply a script tag with an id and a custom attribute data-token (which is the unique access token of the User for that session). The source file for this script is susi-chatbot.js. This is the file that is responsible for displaying the Chatbot on the screen. But, let’s say that you configured your Chatbot in the entire Botbuilder process. So, we need to have a Preview button which could show us a preview of the Chatbot with the chosen configurations, otherwise we would have to test it out by embedding it on our website, which would be tiresome. How does the Preview Button work? The code for Botbuilder page is in the Botbuilder.js file. The code for the Preview button is as follows : {!this.state.chatbotOpen?(<RaisedButton label='Preview' style={{ width: '148px' }} onClick={this.injectJS} />):(<RaisedButton label='Close Preview' style={{ width: '148px' }} onClick={this.handleChatbotClose} />)}   It can be seen that on clicking the ‘Preview’ button, injectJS() function is called, and on clicking the ‘Close Preview’ button, handleChatbotClose() function is called. injectJS = () => { const myscript = document.createElement('script'); myscript.type = 'text/javascript'; myscript.id = 'susi-bot-script'; myscript.setAttribute('data-token',cookies.get('loggedIn')); myscript.src = '/susi-chatbot.js'; myscript.async = true; document.body.appendChild(myscript); // some code }; handleChatbotClose = () =>{ // some code $('#susi-launcher-container').remove(); $('#susi-frame-container').remove(); $('#susi-launcher-close').remove(); $('#susi-bot-script').remove(); }   The above 2 functions are the key functions in understanding how the Preview button is previewing the Chatbot on the screen. Let us see the functioning of injectJS() function first. Firstly, the createElement() method creates an element node of type ‘script’. We store this element node in a variable myscript. We then add attribute values to the script tag by using myscript.attribute_name = attribute_value. We can add ‘type’, ‘id’, ‘src’ and ‘async’ attributes in this way because they are predefined attributes. However, we need to also add a custom attribute to store the access_token of the User, because we would need to pass down this information to detect the owner of the Chatbot. To add a custom attribute, we use the following code : myscript.setAttribute('data-token',cookies.get('loggedIn'));   This add a custom attribute ‘data-token’ and sets its value to the access token of the session, which would later be used to identify the User. This script is then appended to the body of the document. As soon as the script is appended to the page,…

Continue ReadingAdding feature to preview chatbot

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

Fetching Skills using the ID of a user

The Dashboard on the SUSI Skill CMS is the page where all user specific Skill information is being displayed. It also has a section called “My Skills” which displays the Skills created by the user himself. The data for the “My Skills” section has to be fetched from the Skill metadata of each Skill. Hence, this blog post explains how the Skills created by an author are fetched using an API which takes author’s email as the only parameter. Why is such an API required? The task of displaying the “My Skills” section cannot be done entirely on the Client side with the use of existing APIs, as that would result in a lot of AJAX calls to the Server, because for each Skill, there would have to be an AJAX call for each user. Hence, we had to create an endpoint which could directly return the list of Skills created by a user using his ID. This would prevent multiple AJAX calls to the Server. The endpoint used is: "https://api.susi.ai/cms/getSkillsByAuthor.json?author_email="+author_email   Here, author_email is the email of the author who published the particular Skill, which is fetched from the Skill metadata object which looks like this: "Antonyms": { // skill metadata "author_email": akjn11@gmail.com, // skill metadata } Working of the API The code to fetch the Skills created by an author is described in the GetSkillsByAuthor.java file. This API accepts either the author’s name, or the author’s email as the parameter. In our We get all folders within a folder using the following method: private void listFoldersForFolder(final File folder, ArrayList<String> fileList) { File[] filesInFolder = folder.listFiles(); if (filesInFolder != null) { Arrays.stream(filesInFolder).filter(fileEntry -> fileEntry.isDirectory() && !fileEntry.getName().startsWith(".")).forEach(fileEntry->fileList.add(fileEntry.getName() + "")); } }   We use this method to get list of folders of all the group names for all the different Skills, and store them in a variable ‘folderList’ as per the following code: File allGroup = new File(String.valueOf(model)); ArrayList<String> folderList = new ArrayList<String>(); listFoldersForFolder(allGroup, folderList);   For every folder corresponding to a group name, we traverse inside it and then further traverse inside the language folders to reach the place where all the Skill files are stored. This is the code for the method to get all files within a folder: private void listFilesForFolder(final File folder, ArrayList<String> fileList) { File[] filesInFolder = folder.listFiles(); if (filesInFolder != null) { Arrays.stream(filesInFolder).filter(fileEntry -> !fileEntry.isDirectory() && !fileEntry.getName().startsWith(".")).forEach(fileEntry->fileList.add(fileEntry.getName() + "")); } }   We need to get all Skill files inside the ‘languages’ folder, which itself is in ‘group’ folder. This is the code required to implement the same: for (String temp_group_name : folderList){ File group = new File(model, temp_group_name); File language = new File(group, language_name); ArrayList<String> fileList = new ArrayList<String>(); listFilesForFolder(language, fileList); for (String skill_name : fileList) { // get skill metadata of each skill iteratively and put it in result JSONObject accordingly } } }   This is how the Skill metadata is fetched from the getSkillMetadata() method of SusiSkill class: skill_name = skill_name.replace(".txt", ""); JSONObject skillMetadata = SusiSkill.getSkillMetadata(model_name, temp_group_name, language_name, skill_name); if(skillMetadata.get("author_email").equals(author_email))…

Continue ReadingFetching Skills using the ID of a user

Implementing API to Fetch all Ratings by a User on Different Skills on SUSI.AI Web Client

SUSI Skill CMS allows the users to rate any Skill on a scale of 1 to 5. The user can also provide a feedback to any Skill. This paves the path to implementing a Dashboard, which has all the analytic data of the user. Hence, an API needed to be implemented which could return the ratings done by a particular user on all different Skills. How are servlets implemented 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(). Implementing a servlet to fetch all ratings by a user on different Skills The task of this servlet is to fetch all the ratings done by a user on all the different Skills, so that this fetched data could be used later on for implementation of various user specific features like Dashboard page. This is the implementation of the 4 methods of this servlet: @Override public UserRole getMinimalUserRole() { return UserRole.USER; } @Override public JSONObject getDefaultPermissions(UserRole baseUserRole) { return null; } @Override public String getAPIPath() { return "/cms/getProfileDetails.json"; } @Override public ServiceResp onse serviceImpl(Query query, HttpServletResponse response, Authorization authorization, final JsonObjectWithDefault permissions) throws APIException { JsonTray fiveStarSkillRating = DAO.fiveStarSkillRating; // JSONObject and JsonArray Declarations // Checking if access_token has been given and is valid if (authorization.getIdentity() == null) { throw new APIException(400, "Specified user data not found, ensure you are logged in"); } // Fetching email of the user from access token and storing it in a string String email = authorization.getIdentity().getName(); // Iterating over the fiveStarSkillRating JsonTray by extracting keys at every level and accessing their child objects through the extracted keys for(String model_name : fiveStarSkillRating.keys()) { // Storing the list of group names and iterating over them for(String group_name : groupnameKeysList) { // Storing the list of language names and iterating over them for(String language_name : languagenameKeysList) { // Storing the list of skill names and iterating over them for(String skill_name : skillnamesKeysList) { skillnameArray = languageObject.getJSONArray(skill_name); // Iterating over the different Skill JSONObjects for(int i=0; i<skillnameArray.length(); i++) { String jsonEmail = skillnameArray.getJSONObject(i).get("email").toString(); if(jsonEmail.equals(email)) { // If the Skill has been rated by the required author, then put the Skill…

Continue ReadingImplementing API to Fetch all Ratings by a User on Different Skills on SUSI.AI Web Client

Implementing API to facilitate changing review status of a Skill

As any registered user can make Skills in SUSI Skill CMS, sometimes the Skill made is not up to the mark to be displayed on the CMS site. There needs to be a feature implemented where the Admin and higher user roles can review a Skill and approve it accordingly. Then only the approved Skills should be displayed on the Skill CMS. This feature required implementation of an API to allow Admin and higher user roles to change the review status of a Skill. This blog post explains how such an API has been implemented. Implementing a servlet to allow changing review status of a Skill The basic task of the servlet is to allow Admin and higher user roles to allow changing the review status of a Skill. The review status of a Skill can either be ‘true’, indicating that the Skill has been approved by the Admin, or ‘false’, which would indicate that the Skill still needs some improvements before it is actually displayed on the SUSI Skill CMS. Here is the implementation of the API: The API should be usable to only the users who have a user role Admin or higher. Only those with minimum Admin rights should be allowed to control what Skills are displayed on the CMS site. This is implemented as follows: @Override public UserRole getMinimalUserRole() { return UserRole.ADMIN; }   The endpoint for the API is ‘/cms/changeSkillStatus.json’. This is implemented as follows: @Override public String getAPIPath() { return "/cms/changeSkillStatus.json"; }   The main method of the servlet is the serviceImpl() method. This is where the actual code goes which will be executed each time the API is called. This is implemented as follows: @Override public ServiceResponse serviceImpl(Query call, HttpServletResponse response, Authorization authorization, JsonObjectWithDefault permissions) throws APIException { // Store the query parameters in variables if(skill_name == null || !(reviewed.equals("true") || reviewed.equals("false"))) { throw new APIException(400, "Bad service call, missing arguments."); } JSONObject result = new JSONObject(); JsonTray skillStatus = DAO.skillStatus; JSONObject modelName = new JSONObject(); JSONObject groupName = new JSONObject(); JSONObject languageName = new JSONObject(); JSONObject skillName = new JSONObject(); if(reviewed.equals("true")) { JSONObject reviewStatus = new JSONObject(); reviewStatus.put("reviewed", true); // traverse through the skillStatus.json file down to the Skill name and put review status ‘true’ in it skillName.put("reviewed", true); result.put("accepted", true); result.put("message", "Skill review status changed successfully."); return new ServiceResponse(result); } // deleting skill name from skillStatus.json file if it’s review status is being changed to ‘false’ else { if (skillStatus.has(model_name)) { modelName = skillStatus.getJSONObject(model_name); if (modelName.has(group_name)) { groupName = modelName.getJSONObject(group_name); if (groupName.has(language_name)) { languageName = groupName.getJSONObject(language_name); if (languageName.has(skill_name)) { languageName.remove(skill_name); skillStatus.remove(model_name); } skillStatus.commit(); } } } } result.put("accepted", true); result.put("message", "Skill review status changed successfully."); return new ServiceResponse(result); } }   The list of reviewed Skills is being stored in the ‘skillStatus.json’ file. So we need to traverse through that file and store the review status of the Skill as required while making the API call. The API takes 5 parameters: Model of the Skill Group of the Skill Language of…

Continue ReadingImplementing API to facilitate changing review status of a Skill

Use of Flux Architecture in SUSI.AI

SUSI Web Chat is based on Flux, a React.js Architecture. It provides a simple way for implementing many features in SUSI Web Chat. This blog post explains how Flux Architecture works, and also how it is used in SUSI Web Chat to implement the feature of switching between Light and Dark themes. What is Flux? Flux is a micro-architecture for software application development. It is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. Flux Overview As can be seen from the above diagram, Flux has four main components: Component Description Actions Helper methods that pass data to the Dispatcher. Dispatcher Receives these Actions and broadcast payloads to registered callbacks. Stores The Stores that are registered to the Dispatcher will update the Views accordingly. Views  Views are actually React Components that grab the state from the stores and then pass it down to the child components. How these 4 components work together? Application Initialisation: Stores let the registered Dispatcher know that they want to be notified whenever an action comes in. Then the controller views ask the stores for the latest state. When the stores give the state to the controller views, they pass that state along to their child views to render. The controller views also ask the stores to keep them notified when state changes so that they can re-render accordingly. The Data Flow: Once the setup is done, the application is ready to accept user input. So let us trigger an action by having the user make a change. The view tells the action creator to prepare an action. The action creator formats the action and sends it off to the Dispatcher. The Dispatcher dispatches the action off to all of the stores in sequence. Then the store decides whether it cares about this action or not, and changes the state accordingly. Once it’s done changing state, the store lets its subscribed view controllers know. Those view controllers will then ask the store to give them the updated state. After the store gives it the state, the view controller will tell its child views to re-render based on the new state. So this is how Flux works. Now let us see an example of Flux being used in SUSI Web Chat. Use of Flux Architecture to Switch Between Themes in SUSI Web Chat Different Flux components used in SUSI Web Chat: Actions - Settings.actions.js Dispatcher - ChatAppDispatcher.js Store - UserPreferencesStore.js View - MessageSection.react.js Let us now see in detail how we are able to switch themes: In the MessageSection.react.js file, we have the following functions to handle theme change: handleThemeChanger = () => { //code this.applyLightTheme(); } applyLightTheme = () =>{ //code Actions.settingsChanged(settingsChanged); }   Hence, the view tells the action creator to prepare an action. Now, the settingsChanged() function in Settings.actions.js file is called as follows: export function settingsChanged(settings) { ChatAppDispatcher.dispatch({ type: ActionTypes.SETTINGS_CHANGED, settings }); //code }   Hence, the process of…

Continue ReadingUse of Flux Architecture in SUSI.AI

Skill Development using SUSI Skill CMS

There are a lot of personal assistants around like Google Assistant, Apple’s Siri, Windows’ Cortana, Amazon’s Alexa, etc. What is then special about SUSI.AI which makes it stand apart from all the different assistants in the world? SUSI is different as it gives users the ability to create their own skills in a Wiki-like system. You don’t need to be a developer to be able to enhance SUSI. And, SUSI is an Open Source personal assistant which can do a lot of incredible stuff for you, made by you. So, let’s say you want to create your own Skill and add it to the existing SUSI Skills. So, these are the steps you need to follow regarding the same - The current SUSI Skill Development Environment is based on an Etherpad. An Etherpad is a web-based collaborative real-time editor. https://dream.susi.ai/ is one such Etherpad. Open https://dream.susi.ai/ and name your dream (in lowercase letters). Define your skill in the Etherpad. The general skill format is ::name <Skill_name> ::author <author_name> ::author_url <author_url> ::description <description> ::dynamic_content <Yes/No> ::developer_privacy_policy <link> ::image <image_url> ::term_of_use <link> #Intent User query1|query2|query3.... Answer answer1|answer2|answer3...   Patterns in query can be learned easily via this tutorial. Open any SUSI Client and then write dream <your dream name> so that dreaming is enabled for SUSI. Once dreaming is enabled, you can now test any skills which you’ve made in your Etherpad. Once you’ve tested your skill, write ‘stop dreaming’ to disable dreaming for SUSI. If the testing was successful and you want your skill to be added to SUSI Skills, send a Pull Request to susi_skill_data repository providing your dream name. How do you modify an existing skill? SUSI Skill CMS is a web interface where you can modify the skills you’ve made. All the skills of SUSI are directly in sync with the susi_skill_data. To edit any skill, you need to follow these steps - Login to SUSI Skill CMS website using your email and password (or Sign Up to the website if you haven’t already). Click on the skill which you want to edit and then click on the “edit” icon. You can edit all aspects of the skill in the next state. Below is a preview: Make the changes and then click on “SAVE” button to save the skill. What’s happening Behind The Scenes in the EDIT process? SkillEditor.js is the file which is responsible for keeping a check over various validations in the Skill Editing process. There are certain validations that need to be made in the process. Those are as follows - Check whether User has logged in or not if (!cookies.get('loggedIn')) { notification.open({ message: 'Not logged In', description: 'Please login and then try to create/edit a skill', icon: <Icon type='close-circle' style={{ color: '#f44336' }} />, }); this.setState({ loading: false }); return 0; }   Check whether Commit Message has been entered by User or not if (this.state.commitMessage === null) { notification.open({ message: 'Please add a commit message', icon: <Icon type='close-circle' style={{ color: '#f44336' }} />,…

Continue ReadingSkill Development using SUSI Skill CMS

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

SUSI.AI User Roles and How to Modify Them

In this blog, I discuss what is ‘user-role’ in SUSI.AI, what are the various roles and how SUSI admins can modify/update a user’s roles. What is User Role? A UserRole defines the servlet access right. Not all users are allowed to access all the data and services. For  example, To list all the users, minimal user role expected is ADMIN. This classification of users are inspired by the wikipedia User Access Levels, see https://en.wikipedia.org/wiki/Wikipedia:User_access_levels.While querying SUSI, Users are classified into 7 different categories, namely : BOT ANONYMOUS USER   REVIEWER ACCOUNTCREATOR ADMIN BUREAUCRAT * Please see that these are as of the date of publish of this blog. These are subject to change, which is very unlikely. If SUSI is active as a bot on some bot integrated platform (like line or kik), the user role assigned to it will be that of BOT. This user role just has technical access to the server. All the users who are not logged in but interacting with SUSI are ANONYMOUS users. These are only subject to chat, login and signup. They may use forgot password service and reset password services as well. Once a user login to the server, a token is generated and sent back to client to maintain the identity, hence acknowledging them as USER(s). Users with role assigned as “REVIEWERS” are expected to manage the Skill CMS. There might be some dispute or conflict in a skill. REVIEWERS then take the access of skill data and finalise the conflict there itself for smooth functionality. ADMIN users are those who have special rights with them. These are more like moderators with much special rights than any other user. At the top level of the hierarchy are the BUREAUCRATS. These users have more rights than anyone. They can change role of any other user, override decision of any ADMIN user as well. Both admins and bureaucrats have the access to all the settings file on the server. They not only can look at the list, but also download and upload them. Now these users also have right to upgrade or downgrade any other user as well. All these user roles are defined in UserRole.java file. In each request received by the server, the user role of user making the request is compared with the minimal user role in getMinimalUserRole() method. This method is defined in AbstractAPIHandler which validates if a user is allowed to access a particular servlet or not. private void process(HttpServletRequest request, HttpServletResponse response, Query query) throws ServletException, IOException { // object initialisation and comparsions // user authorization: we use the identification of the user to get the assigned authorization Authorization authorization = DAO.getAuthorization(identity); if (authorization.getUserRole().ordinal() < minimalUserRole.ordinal()) { response.sendError(401, "Base user role not sufficient. Your base user role is '" + authorization.getUserRole().name() + "', your user role is '" + authorization.getUserRole().getName() + "'"); return; } // evaluations based on other request parameters. } Now that we know about what User Roles actually are, let us look at how…

Continue ReadingSUSI.AI User Roles and How to Modify Them