Using Our Javascript Library

We just made available our Javascript library, which so far is pretty basic but will allow you to call your iKnode apps from your Web applications or mobile apps.

The purpose of this post is to show you the usage of this library, as an example we will develop a password manager app on iKnode, so basically it will allow us to:

  • Store a new password entry.
  • List current passwords.
  • Update and delete passwords.

So our password entry which in this case we’d call Credential, consists of the following fields:

  • Id
  • Name
  • Login
  • Password

Ok, so the first step is to create our iKnode application, so we go ahead to iKnode Command Center Application Editor and code. This application was shown as a demo in MobileDevNJ

Password Manager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.Text;

using iKnode.Applications;
using iKnode.Applications.Data;

namespace MobileDevNJ
{
    /// <summary>
    /// Defines the Password Manager Application.
    /// </summary>
    [Application]
    public class PasswordManager
    {
        /// <summary>
        /// Executing User Identifier.
        /// </summary>
        private static readonly Guid UserId = new Guid(""); // Put your userId here.

        /// <summary>
        /// Repository Instance.
        /// </summary>
        private static DocumentRepository Repository = new DocumentRepository(UserId);

        /// <summary>
        /// Collection Name.
        /// </summary>
        private static readonly string CollectionName = "PasswordManager";

        /// <summary>
        /// Returns the list of items.
        /// </summary>
        /// <returns>List of Items in JSON.</returns>
        public string GetList()
        {
            PagedList<Document> items = Repository.GetPagedList(CollectionName);
            return DocumentFactory.DocListToJson(items.List).Replace(Environment.NewLine, String.Empty);
        }

        /// <summary>
        /// Returns the selected item (if found) by identifier.
        /// </summary>
        /// <param name="id">Item identifier.</param>
        /// <returns>Found Item in JSON, <c>String.Empty</c> otherwise..</returns>
        public string GetById(string id)
        {
            Document item = Repository.QueryScalar(CollectionName, "{ \"Id\": \""+id+"\" }");
            if(item != null) {
                return item.ToJson();
            }

            return String.Empty;
        }

        /// <summary>
        /// Returns the selected item (if found) by name.
        /// </summary>
        /// <param name="name">Item name.</param>
        /// <returns>Found Item in JSON, <c>String.Empty</c> otherwise.</returns>
        public string GetByName(string name)
        {
            Document item = Repository.QueryScalar(CollectionName, "{ \"Name\": \""+name+"\" }");
            if(item != null) {
                return item.ToJson();
            }

            return String.Empty;
        }

        /// <summary>
        /// Adds a new item and returns the item's identifier if successful.
        /// </summary>
        /// <param name="name">Item Name.</param>
        /// <param name="login">Item Login.</param>
        /// <param name="password">Item Password.</param>
        /// <returns>New Item Identifier.</returns>
        public string AddNew(string name, string login, string password)
        {
            Document item = CreateItem(null, name, login, password);
            item["Id"] = Repository.Save(item);

            return item["Id"];
        }

        /// <summary>
        /// Updates an existing item.
        /// </summary>
        /// <param name="id">Item Identifier.</param>
        /// <param name="name">Item Name.</param>
        /// <param name="login">Item Login.</param>
        /// <param name="password">Item Password.</param>
        public void Update(string id, string name, string login, string password)
        {
            Document item = Repository.QueryScalar(CollectionName, "{ \"Id\": \""+id+"\" } ");
            if(item == null) {
                throw new Exception("Item with id '"+id+"' not found.");
            }

            item["Name"] = name;
            item["Login"] = login;
            item["Password"] = password;

            Repository.Save(item);
        }

        /// <summary>
        /// Deletes an existing item.
        /// </summary>
        /// <param name="id">Item Identifier.</param>
        public void Delete(string id)
        {
            Document item = Repository.QueryScalar(CollectionName, "{ \"Id\": \""+id+"\" } ");
            if(item == null) {
                throw new Exception("Item with id '"+id+"' not found.");
            }

            Repository.Delete(item);
        }

        /// <summary>
        /// Creates an Item Document.
        /// </summary>
        /// <param name="id">Item Identifier.</param>
        /// <param name="name">Item Name.</param>
        /// <param name="login">Item Login.</param>
        /// <param name="password">Item Password.</param>
        /// <returns>Item Document.</returns>
        private static Document CreateItem(string id, string name, string login, string password)
        {
            Document item = new Document(CollectionName);
            item["Name"] = name;
            item["Login"] = login;
            item["Password"] = password;

            if(!String.IsNullOrEmpty(id)) {
                item["Id"] = id;
            }

            return item;
        }
    }
}

So the application basically provides methods for the usual CRUD operations, just as a reminder, only the public methods in your iKnode app will be, let’s say, callable as tasks, the private method will not be visible, it is more a support method.

Then we save, compile and publish our app and make sure it appears in our app library:

Remeber to set the name of your app in the Properties tab in the editor, the Class does not act as the application name. So let’s go ahead and test our new app:

1
2
3
4
5
6
curl -X POST
     -d "{\"parameters\":\"{}\"}"
     -H "Content-Type:application/json"
     -H "iKnode-UserId:<YOUR_OWN_USER_ID>"
     -H "iKnode-ApiKey:<YOU_OWN_API_KEY>"
     https://api.iknode.com/Applications/execute/PasswordManager/GetList

We should get a JSON array of credential entries.

The next step is to show how to call this iKnode app from our web app, we’ll develop a simple chrome extension that will show a grid with the current passwords, we’d be using ExtJS 4.1 to render our widgets. You can browse the example extension here.

As you can see there’s a file called iknode-client-0.1.min.js which is our library, this is a minified version but you should be able to view it here in our clients repository.

Edit agent.js and go near line 59, this is where we create an instance of the client and provide our user id and api key:

1
var client = new iknode.Client({userId:'<YOUR_USER_ID>' , apiKey: '<YOUR_APIKEY_ID>'});

Then you just need to call the exec(config) function, where config has the following structure:

1
{ task: 'taskexpr', params: '', [callback]:''}

The field task must contain the task we want to execute, the task name follows the pattern ApplicationName:Method, so in our case we want to list the credentials, thus, our task would be PasswordManager:GetList considering you did not change the method names from the example iKnode app provided above and you set your app name to be PasswordManager, if choosed a different application name you must use that one instead. The callback field is optional, you can avoid it if you are executing and don’t care about the server response.

Our call looks like this:

1
2
3
4
5
response = client.exec({ task: 'PasswordManager:GetList',
           params: iknode.Client.EMPTY_PARAMS,
           callback: function(result) {
                 // callback method body
                 }});

As you can see we provided the task name we mentioned, and as for the parameters we are using a constant already defined in our library for empty params, you should be using it in case that your tasks requires no parameters, but if we need to send the password name, our call would be

1
2
3
4
5
response = client.exec({ task: 'PasswordManager:GetByName',
           params: "{\"parameters\":\"{'name':'credential_name'}\"}",
           callback: function(result) {
                 // callback method body
                 }});

You should be able to see the full callback method in the example code, we process the response text a bit, the result parameter constains the raw responseText obtained from the server, and then we parse to get an array of objects which in this case we iterate to populate the GridPanel.

Hope this post helps to get you started with our javascript library, we’d be pleased to hear comments from you or help you solve any doubts you might have.

Happy coding!