User Tools

Site Tools


userspace:json-rpc_angularjs

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
userspace:json-rpc_angularjs [2015/05/01 13:37]
justcoding
userspace:json-rpc_angularjs [2021/08/23 08:37] (current)
Line 1: Line 1:
 +====== Angular JSON-RPC ======
 Yet another method of reading the JSON-RPC interface. Yet another method of reading the JSON-RPC interface.
  
 The example below reads the result of the latest softwareAudit and displays it as a table. Information about installed sw products are merged in. The example below reads the result of the latest softwareAudit and displays it as a table. Information about installed sw products are merged in.
  
-All needed files (.html, .js, .css) should be hosted below /usr/share/opsiconfd/static/AngularExample folder thus avoiding cross scripting complaints of modern browsers.+All needed files (.html, .js, .css) should be hosted below /usr/share/opsiconfd/static/AngularExample folder. This way no other Webserver is involved and cross scripting complaints by the browser are avoided.
  
 The location would then read https://opsi:4447/AngularExample. The location would then read https://opsi:4447/AngularExample.
 +
 +====== Prerequisites ======
 +Of course its helpful to load the angular-min.js (or angular.js for development) from an appropriate location. The example uses a local copy.
  
 ====== Minor Obstacles ====== ====== Minor Obstacles ======
-configed will currently answer /rpc? requests with Encoding "deflate", but will anounce it as "gzip". This issue is known and a patch is mentioned in the forums.+opsiconfd will currently answer /rpc? requests with Encoding "deflate", but will anounce it as "gzip". This currently prevents any browser from even reading the opsiconfd answer. The responsible Worker.py needs a small change to answer requests from a browser //and// Winst.exe (and other legacy opsi clients) as well. The issue is known and a patch is [[https://forum.opsi.org/viewtopic.php?f=6&t=7449|mentioned in the forums]].
  
 Most requests require a logon, some even special rights. The script user should be member of a new group //opsireader// and the **acl.conf** file should be prepended with appropriate lines: Most requests require a logon, some even special rights. The script user should be member of a new group //opsireader// and the **acl.conf** file should be prepended with appropriate lines:
Line 17: Line 21:
 product_get.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver; self; opsi_client product_get.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver; self; opsi_client
 </file> </file>
 +
 +====== Calling Parameter ======
 +When called as /AngularExample/?{"dns":"clientID.domain.local"}
 +the SoftwareAudit of the given clientId is displayed. OPSI client names may be entered in an input field at any time and are queried asynchronously.
 +
 +The strange format of the query string as json has its reason: it is needed for the AndroidApp named [[https://play.google.com/store/apps/details?id=eu.dirtyharry.opsiadmin|OPSI Admin]]. The App can read barcodes/QRcodes formatted this way in order to open the details of the identified client. Nice feature when the barcode sticks on the client. 
 +
 +What if the barcode appears right on the client's screen? Try this Java app: [[https://github.com/GallusMax/opsi/tree/master/opsi-barcode|Opsi-Barcode]]
 +====== The Code ======
 +<code>
 +/usr/share/opsiconfd/static/AngularExample
 +  ├ index.html
 +  ├ angular.js
 +  ├ swinv.js
 +  └ swinv.css
 + </code>
 +
 +======= index.html =======
 +Where all other is loaded from..
 +<code html>
 +<!DOCTYPE html>
 +<html ng-app="opsi-swinv">
 +<head>
 +    <link rel="stylesheet" type="text/css" href="swinv.css" >
 +    <script type="text/javascript" src="angular.js"></script> <!-- chenge to angular-min for production -->
 +    <!-- script type="text/javascript" src="angular-resource.js"></script -->
 +    <script type="text/javascript" src="swinv.js"></script>
 +    <script type="text/javascript" src="swpattern.js"></script>
 +</head>
 +
 +<body ng-controller="swinvController as sw">
 +
 +<div class="swlist">
 +
 +<input id="inputId" ng-model="sw.clientId"></input>
 +<button ng-click="sw.refresh(sw.clientId)">refresh list</button>
 +
 +
 +<table border >
 +  <tr><th>Name</th><th>Version</th><th>Lizenz</th><th>Installationsgrund</th></tr>
 +
 +<tr ng-repeat="swp in sw.products" ng-show="sw.nonMS(swp.name)">
 +<td>{{swp.name}} </td>
 +<td> {{swp.version}}</td>
 +<td>{{sw.reason(swp.name)}}</td>
 +<td class={{sw.csswarn(swp.name)}}><span ng-show="!sw.isOpsi(swp.name)">{{sw.reason(swp.name)}} </span>{{sw.opsiProdId(swp.name)}}</td>
 +</tr>
 +</table>
 +
 +<br/><label><input type="checkbox" ng-model="sw.showopsiinstalled" />installed OPSI products on this client <span>({{sw.clientId}})</span></label>
 +<div ng-show="sw.showopsiinstalled">
 +<table border>
 +  <tr><th>OpsiProduct</th></tr>
 +  <tr ng-repeat="inst in sw.installed">
 +    <td>{{inst}}</td>
 +  </tr>
 +</table>
 +</div>
 +
 +<br/><label><input type="checkbox" ng-model="sw.showallprods" />available products</label>
 +<table ng-show="sw.showallprods" border width="100%">
 +  <tr><th>productInfo</th><th>productId</th><th>...............................................</th></tr>
 +  <tr ng-repeat="prod in sw.productinfos">
 +    
 +    <td>{{prod.productId}}</td>
 +    <td>{{prod.name}}</td>
 +    <td></td>
 +  </tr>
 +</table>
 +
 +</div>
 +</body>
 +</html>
 +</code>
 +
 +======= swinv.js =======
 +The AngularJS mimic..
 +<code JavaScript>
 +(function(){
 +    var app = angular.module('opsi-swinv', []);
 +  
 +    app.controller('swinvController',function($http,$filter){
 +
 + this.showallprods=0;
 + this.showopsiinstalled=0;
 + baseurl='/rpc';
 + logonurl='https://testerMemberOfGroupopsireader:unGuessablePassword@'+window.location.host+'/rpc';
 +
 + this.clientId="defaultclient.domain.local";
 +
 + this.auditParams={'id':'jsonrpc','method':'auditSoftwareOnClient_getObjects','params':[]};
 + this.auditParams.params.push([]);
 + this.auditParams.params.push({"clientId":"defaultclient.domain.local"});
 +
 + me=this;
 + me['installed']=[];
 + me['productinfos']=[];
 +
 + this.jsonParmDns=function(){
 +     this.search=window.location.search;
 +     if (this.search.match(/dns/)){ // we believe in barcode like {"dns":"<clientId>"}
 + var qsearch=decodeURIComponent(this.search).match(/{.+dns.+:.+}/);
 + var jsonsearch=decodeURIComponent(qsearch); // get the json 
 + return angular.fromJson(jsonsearch).dns;
 +// return JSON.parse(jsonsearch).dns;
 +     }
 +     return null;
 + };
 +
 + this.opsicall=function(field,method,arg){
 +        Params={'id':'1','method':method,'params':[]};
 +     if(arg)Params.params[0]=arg;
 +     $http.post(baseurl,Params)
 + .success(function(response,stat,head,conf){
 +//     alert("success: "+$filter('json')(response));
 +     me.opsires="success: "+method;
 +     me.opsiconf=conf;
 +     if(response.error)
 + alert(response.error.message);
 +     else
 + me[field]=response.result;
 +   
 + })
 + .error(function(err,stat,head,conf){
 +     me.opsires="error";
 +     alert("err: "+(err)+stat+head+$filter('json')(conf));
 +     me.opsistat=stat;
 +     me.opsihead=head;
 +     me.opsiconf=conf;
 + });
 +
 + };
 +
 + this.logon=function(){
 +     $http.post(logonurl,this.logonParams)
 + .success(function(response){
 +//     alert("success: "+$filter('json')(response));
 +     // call after logon success
 +     me.getproductinfos(); 
 +     me.refresh(me.clientId);
 + })
 + .error(function(response){
 +     alert("err: "+(response));
 + });
 + };
 +
 + this.getprods=function(id){
 +     this.opsires="calling.. "+id;
 +     if(id)this.auditParams.params[1].clientId=id;
 +     $http.post(baseurl,this.auditParams)
 + .success(function(response,stat,head,conf){
 +    // alert("success: "+response);
 +     if(response.error)alert(response.error.message);
 +     me.products=response.result;
 +     me.opsistat=stat;
 +     me.opsihead=head;
 +     me.opsiconf=conf;
 + })
 + .error(function(err,stat,head,conf){
 +     me.opsires="error";
 +     alert("err: "+(err)+stat+head+$filter('json')(conf));
 +     me.opsistat=stat;
 +     me.opsihead=head;
 +     me.opsiconf=conf;
 + });
 +     
 + };
 +
 + // get products on Client with id
 + this.getinstalled=function(id){
 +     this.opsicall('installed','getInstalledLocalBootProductIds_list',id);
 + };
 +
 + // get all available OPSi products
 + this.getproductinfos=function(){
 +     this.opsicall('productinfos','getProducts_listOfHashes');
 + };
 +
 + this.logon();
 + this.clientId=this.jsonParmDns();
 +// this.getproductinfos(); 
 +
 + this.refresh=function(id){
 +     if(null != id){
 + this.getprods(id);
 + this.getinstalled(id);
 +     }
 + };
 +
 +
 + this.nonMS=function(name){
 +//     return true;
 +     if(name.match(/AddressBook/)) return false;
 +     if(name.match(/^Connection Manager/)) return false;
 +     if(name.match(/^DirectDrawEx/)) return false;
 +     if(name.match(/^DXM_Runtime/)) return false;
 +     if(name.match(/^Fontcore/)) return false;
 +     if(name.match(/KB[0-9]+/))  return false;
 +     if(name.match(/Microsoft/)) return false;
 +     if(name.match(/^MPlayer2/)) return false;
 +     if(name.match(/^Outlook/)) return false;
 +     if(name.match(/^[iI][Ee]/)) return false;
 +     if(name.match(/^Windows/)) return false;
 +     if(name.match(/^MobileOptionPack/)) return false;
 +     if(name.match(/^SchedulingAgent/)) return false;
 +     if(name.match(/^WIC/)) return false;
 +     return true;
 + }
 +
 +
 + this.pattern=swpattern;
 +
 + this.reason=function(name){
 +     for(p in this.pattern){
 + if(name.match(p))
 +     return this.pattern[p];
 +     }
 +     
 + };
 +
 + // guess the corresponding OPSI productId from the Windows Product name
 + this.opsiProdId=function(name){
 +     for(i=0; i<this.productinfos.length;i++){
 + p=this.productinfos[i];
 + if(p.name && name.match(p.name)||name.match(p.productId))
 +     return p.productId;
 +     }
 +     return null;
 + };
 + // convenience: is this an OPSI product?
 + this.isOpsi=function(name){
 +     return (null != this.opsiProdId(name));
 + };
 +
 + // mark rows w/o reason/license
 + this.csswarn=function(name){
 +     if(this.isOpsi(name) || this.reason(name))
 + return "ng-binding";
 +     else
 + return "warn";
 + };
 +
 +
 +    });
 +
 +
 +    var swpattern={'^Audacity':'OpenSource',
 +    '^Java':'Oracle',
 +    '^Mozilla ':'Mozilla Public',
 +    '^OpenOff':'OpenSource',
 +    '^Google':'Google Public',
 +    '^Adobe Flash':'Adobe Public',
 +    '^OpenSSL':'OpenSource',
 +    '^Python':'OpenSource'
 +
 +   };
 +
 +
 +
 +
 +})();
 +</code>
 +
 +======= swinv.css =======
 +
 +some tweaking of the appearance - anything goes..
 +<code css>
 +body {
 +    font-family: "Comic Sans M$", Arial, Helvetica, sans-serif;
 +}
 +
 +table{
 +    width: 100%;
 +    border-collapse: collapse;
 +}
 +
 +td, th {
 +    font-size: 1em;
 +    border: 1px solid #aa0093;
 +    padding: 3px 7px 2px 7px;
 +}
 +
 +th {
 +    font-size: 1.1em;
 +    text-align: left;
 +    padding-top: 5px;
 +    padding-bottom: 4px;
 +    background-color: #d30c6b;
 +    color: #ffffff;
 +}
 +
 +label{
 +    background-color: #d30c6b;
 +    color: #ffffff;
 +}
 +
 +
 +td.warn {
 +/* enhance unlicensed products*/
 +    color: #000000;
 +    background-color: yellow;
 +}
 +
 +.ng-binding{
 +//    background-color: blue;
 +font-family: Courier;
 +}
 +</code>
userspace/json-rpc_angularjs.1430487438.txt.gz · Last modified: 2021/08/23 08:37 (external edit)