SECARSP-268 +Implement device policies state request mechanism
authorm.dalakov <m.dalakov@samsung.com>
Tue, 27 Mar 2018 12:45:49 +0000 (15:45 +0300)
committerm.dalakov <m.dalakov@samsung.com>
Tue, 27 Mar 2018 12:46:18 +0000 (15:46 +0300)
server/samserver/src/main/java/com/samsung/samserver/domain/PolicyType.java
server/samserver/src/main/java/com/samsung/samserver/service/PolicesUpdateService.java
server/samserver/src/main/java/com/samsung/samserver/service/impl/PolicesUpdateServiceImpl.java
server/samserver/src/main/java/com/samsung/samserver/web/rest/controller/IRestDashboard.java
server/samserver/src/main/java/com/samsung/samserver/web/rest/service/device/RegisterDeviceRestService.java
server/samserver/src/main/java/com/samsung/samserver/web/rest/service/device/SendDataRestService.java
server/samserver/src/main/java/com/samsung/samserver/web/rest/service/vm/DPolicy.java
server/samserver/src/main/java/com/samsung/samserver/web/rest/service/vm/UIPolicies.java
server/samserver/src/main/resources/config/liquibase/changelog/20180210112802_added_entity_PolicyType.xml
server/samserver/src/main/resources/config/liquibase/changelog/policytype.csv

index 54f33ca..3df51fb 100644 (file)
@@ -34,6 +34,8 @@ public class PolicyType extends AbstractType implements Serializable {
     @Column(name = "mapping")
     private java.lang.String mapping;
 
+    @Column(name = "uitype")
+    private java.lang.String uitype;
 
     public PolicyType category(String category) {
         this.category = category;
@@ -60,4 +62,8 @@ public class PolicyType extends AbstractType implements Serializable {
         return this;
     }
 
+    public PolicyType uitype(String uitype) {
+        this.uitype = uitype;
+        return this;
+    }
 }
index 046c63d..baeed4b 100644 (file)
@@ -22,7 +22,16 @@ public interface PolicesUpdateService {
      * Update device polices.
      *
      * @param device the device
+     * @param policesUpdate the list of policies for update
      */
     void update(Device device, List<UIPolicies.UIPolicy> policesUpdate);
 
+    /**
+     * Prepare state request for device policies
+     *
+     * @param device the device
+     * @param allPolicyTypes list of all policy types for the device
+     */
+    void prepareStateRequest(Device device, List<UIPolicies.UIPolicy> allPolicyTypes);
+
 }
index 11db8f9..342363c 100644 (file)
@@ -36,6 +36,7 @@ public class PolicesUpdateServiceImpl implements PolicesUpdateService {
      * Update device polices.
      *
      * @param device the device
+     * @param policesUpdate the list of policies for update
      */
     @Override
     public void update(Device device, List<UIPolicy> policesUpdate) {
@@ -78,4 +79,52 @@ public class PolicesUpdateServiceImpl implements PolicesUpdateService {
         );
     }
 
+
+    /**
+     * Prepare state request for device policies
+     *
+     * @param device the device
+     * @param allPolicyTypes list of all policy types for the device
+     */
+    @Override
+    public void prepareStateRequest(Device device, List<UIPolicy> allPolicyTypes){
+        log.debug("Prepare request for {}","device policies state");
+        String type = "state-policy";
+        StringBuilder out = new StringBuilder();
+
+        out.append("{\n" +
+                "  \"type\": \"state-policy\",\n" +
+                "  \"policies\": [\n    ");
+
+        int c = 0;
+        int size=allPolicyTypes.size();
+        for (UIPolicy policyUpdate: allPolicyTypes) {
+            out.append(policyUpdate.toJSONDeviceWithoutValue());
+            c++;
+            if (c!=size) out.append(",\n    ");
+        }
+        out.append("\n  ]\n" +"}\n");
+
+        String uuid = updatesService.getUpdateUID(type, out.toString());
+        Optional<Updates> u = updatesService.find(device, type);
+        if (!u.isPresent()) {
+            u = Optional.of(
+                    new Updates()
+                            .type(type)
+                            .descr("action: request device policies state")
+                            .device(device)
+                            .su("n")
+            );
+        }
+
+        updatesService.save(
+                u.get()
+                        .uuid(uuid)
+                        .uri( "/api/device-service/get-udata?duid="+device.getDuid()+"&uuid="+uuid)
+                        .rdate(Instant.now())
+                        .ctime(Instant.now())
+                        .data(out.toString())
+        );
+    }
+
 }
\ No newline at end of file
index 9993f2d..24fc686 100644 (file)
@@ -123,7 +123,7 @@ public interface IRestDashboard {
 
 
     /**
-     * PUT  /polices/device : Update an device policies.
+     * PUT  /policies/device : Update an device policies.
      *
      * @param uiPolicesUpdate list the ui policies to update device policies
      * @return the ResponseEntity with status 200 (OK)
@@ -137,13 +137,13 @@ public interface IRestDashboard {
             @ApiResponse(code = 400, message = "Bad Request. The reason is contained in the tags “errorKey”, “message”, “title”"),
             @ApiResponse(code = 500, message = "Internal server error. The user has to repeat action.")
     })
-    @RequestMapping(value ="/polices/device", method = RequestMethod.PUT)
+    @RequestMapping(value ="/policies/device", method = RequestMethod.PUT)
     public ResponseEntity<List<UIPolicies.UIPolicy>> updateDevicePolicies(
             @ApiParam(value = "device id", required = true) @RequestParam(value = "id") Long id, @Valid @RequestBody UIPoliciesUpdate uiPolicesUpdate);
 
 
     /**
-     * GET  /polices : get all the polices.
+     * GET  /policies : get all the polices.
      *
      * @return the ResponseEntity with status 200 (OK) and the list of polices
      */
@@ -153,13 +153,13 @@ public interface IRestDashboard {
             @ApiResponse(code = 400, message = "Bad Request. The reason is contained in the tags “errorKey”, “message”, “title”"),
             @ApiResponse(code = 500, message = "Internal server error. The user has to repeat action.")
     })
-    @RequestMapping(value ="/polices", method = RequestMethod.GET)
+    @RequestMapping(value ="/policies", method = RequestMethod.GET)
     @ResponseStatus(HttpStatus.OK)
     public ResponseEntity<List<UIPolicies>> getAllPolices();
 
 
     /**
-     * GET  /polices/device?id : get the device polices.
+     * GET  /policies/device?id : get the device polices.
      *
      * @param id the id of the device
      * @return the ResponseEntity with status 200 (OK) and the list of polices
@@ -170,7 +170,7 @@ public interface IRestDashboard {
             @ApiResponse(code = 400, message = "Bad Request. The reason is contained in the tags “errorKey”, “message”, “title”"),
             @ApiResponse(code = 500, message = "Internal server error. The user has to repeat action.")
     })
-    @RequestMapping(value ="/polices/device", method = RequestMethod.GET)
+    @RequestMapping(value ="/policies/device", method = RequestMethod.GET)
     @ResponseStatus(HttpStatus.OK)
     public ResponseEntity<List<UIPolicies>> getDevicePolices(
             @ApiParam(value = "device id", required = true) @RequestParam(value = "id") Long id);
index adccf8b..4ad1766 100644 (file)
@@ -5,8 +5,11 @@
  */
 package com.samsung.samserver.web.rest.service.device;
 
-import com.samsung.samserver.web.rest.service.vm.DInfo;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.samsung.samserver.web.rest.service.vm.*;
 import org.slf4j.*;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.web.bind.annotation.*;
@@ -15,8 +18,9 @@ import com.samsung.samserver.service.*;
 import com.samsung.samserver.web.rest.errors.DeviceServiceError;
 import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
+import java.io.IOException;
 import java.time.Instant;
-import java.util.Optional;
+import java.util.*;
 
 /**
  * REST service implementation for register device.
@@ -32,11 +36,33 @@ public class RegisterDeviceRestService {
     private final DeviceTypeService deviceTypeService;
     private final DeviceService deviceService;
 
+    @Autowired
+    private PolicyTypeService policyTypeService;
+
+    @Autowired
+    private PolicesUpdateService policesUpdateService;
+
     public RegisterDeviceRestService(DeviceTypeService deviceTypeService, DeviceService deviceService) {
         this.deviceTypeService = deviceTypeService;
         this.deviceService = deviceService;
     }
 
+    private  List<UIPolicies.UIPolicy> getUIPolicyList(){
+        Map<String, PolicyType> allPolicies = policyTypeService.findAllAsMap();
+        List<UIPolicies.UIPolicy> uiPolicyList = new ArrayList<>();
+        ObjectMapper mapper = new ObjectMapper();
+        for (Map.Entry<String ,PolicyType> entry : allPolicies.entrySet()) {
+            PolicyType policyType = entry.getValue();
+            try {
+                UIPolicies.UIPolicy uiPolicy = mapper.readValue(policyType.getDefval(), new TypeReference<UIPolicies.UIPolicy>(){});
+                uiPolicyList.add(uiPolicy);
+            } catch (IOException e) {
+                log.error("register device: prepare device policies state request: message: {} stacktrace: {}", e.getMessage(), e.getStackTrace());
+            }
+        }
+        return uiPolicyList;
+    }
+
     public ResponseEntity<String> registerDevice(@Valid @RequestBody DInfo dInfo, HttpServletRequest request) {
         log.debug("request to register device : {}", dInfo);
 
@@ -60,6 +86,9 @@ public class RegisterDeviceRestService {
             .osver(dInfo.getOsver())
             .ipaddr(request.getRemoteAddr())
             .dtype(dt.get()));
+
+        policesUpdateService.prepareStateRequest(result, getUIPolicyList());
+
         return ResponseEntity.ok()
             .headers(new HttpHeaders())
             .body(result.getDuid());
index 72b163a..6c8bc7d 100644 (file)
@@ -78,7 +78,7 @@ public class SendDataRestService {
                 continue;
             }
             try {
-                String uiType = policyType.getCategory();
+                String uiType = policyType.getUitype();
                 UIPolicy uiPolicy = UIPolicy.make(uiType).bind(dPolicy);
                 policyService.update(device, policyType, mapper.writeValueAsString(uiPolicy));
             } catch (JsonProcessingException | NullPointerException e) {
@@ -99,7 +99,7 @@ public class SendDataRestService {
         switch (data.getType()) {
             case "report":
                 return report(device.get(), data.getLogs());
-            case "policies":
+            case "state-policy":
                 return policy(device.get(), data.getPolicies());
             default:
                 throw new DeviceServiceError.DataTypeNotFoundException();
index e9ba320..4a0f7ea 100644 (file)
@@ -26,6 +26,7 @@ public interface DPolicy {
         private String name;
         @NotNull
         private Integer value;
+        private Integer error;
     }
 
     @Getter @Setter @ToString
@@ -36,6 +37,7 @@ public interface DPolicy {
         private String key;
         @NotNull
         private Integer value;
+        private Integer error;
     }
 
     class DPoliciesDeserializer extends StdDeserializer {
index 5f76d8a..5106377 100644 (file)
@@ -53,6 +53,8 @@ public class UIPolicies {
 
         String getName();
         String toJSONDevice();
+        String toJSONDeviceWithoutValue();
+
         UIPolicy bind(DPolicy dPolicy);
         UIPolicy bind(UIPolicyUpdate uiPolicyUpdate);
 
@@ -104,6 +106,7 @@ public class UIPolicies {
             DPolicyInteger dPolicyInteger = (DPolicyInteger)dPolicy;
             name = dPolicyInteger.getName() ;
             value = dPolicyInteger.getValue();
+            state = (dPolicyInteger.getError()!=null) ? 0:1;
             return this;
         }
         @Override
@@ -120,6 +123,12 @@ public class UIPolicies {
                     VALUE + value +
                     "}";
         }
+        @Override
+        public String toJSONDeviceWithoutValue() {
+            return  "{" +
+                    NAME + name + "\"" +
+                    "}";
+        }
     }
 
     @JsonRootName(INTEGER)
@@ -142,6 +151,7 @@ public class UIPolicies {
             DPolicyInteger dPolicyInteger = (DPolicyInteger)dPolicy;
             name = dPolicyInteger.getName() ;
             value = dPolicyInteger.getValue();
+            state = (dPolicyInteger.getError()!=null) ? 0:1;
             return this;
         }
         @Override
@@ -158,6 +168,12 @@ public class UIPolicies {
                     VALUE + value +
                     "}";
         }
+        @Override
+        public String toJSONDeviceWithoutValue() {
+            return  "{" +
+                    NAME + name + "\"" +
+                    "}";
+        }
     }
 
     @JsonRootName(FLAG_SET)
@@ -193,7 +209,8 @@ public class UIPolicies {
         public FlagSet bind(DPolicy dPolicy){
 
             DPolicyIndexed dPolicyIndexed = (DPolicyIndexed)dPolicy;
-            name = dPolicyIndexed.getName() ;
+            name = dPolicyIndexed.getName();
+            state = (dPolicyIndexed.getError()!=null) ? 0:1;
             items = new ArrayList<>();
             int value = dPolicyIndexed.getValue();
             for (int i=0; i<1; i++) {
@@ -225,6 +242,21 @@ public class UIPolicies {
             }
             return s.toString();
         }
+        @Override
+        public String toJSONDeviceWithoutValue() {
+            int c = 0;
+            int size = items.size();
+            StringBuilder s = new StringBuilder();
+            for (FlagSetObject fso: items) {
+                s.append("{")
+                        .append(NAME).append(name).append("\",")
+                        .append("\"key\":\"").append(fso.getKey()).append("\"")
+                        .append("}");
+                c++;
+                if (c!=size) s.append(",");
+            }
+            return s.toString();
+        }
     }
 
     @JsonRootName(MULT_CHOICE)
@@ -259,7 +291,8 @@ public class UIPolicies {
         @Override
         public MultChoice bind(DPolicy dPolicy){
             DPolicyInteger dPolicyInteger = (DPolicyInteger)dPolicy;
-            name = dPolicyInteger.getName() ;
+            name = dPolicyInteger.getName();
+            state = (dPolicyInteger.getError()!=null) ? 0:1;
             items = new ArrayList<>();
             int value = dPolicyInteger.getValue();
             for (int i=0; i<8; i++) {
@@ -290,6 +323,12 @@ public class UIPolicies {
                     VALUE + value +
                     "}";
         }
+        @Override
+        public String toJSONDeviceWithoutValue() {
+            return  "{" +
+                    NAME + name + "\"" +
+                    "}";
+        }
     }
 
 }
\ No newline at end of file
index 2ab7ebd..3d250bf 100644 (file)
                 <constraints nullable="true" />
             </column>
 
+            <column name="uitype" type="varchar(255)">
+                <constraints nullable="true" />
+            </column>
+
             <!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
         </createTable>
 
index afceab8..939f453 100644 (file)
@@ -1,26 +1,26 @@
-id;name;descr;category;opt;defval;supported;mapping
-1;bluetooth;;bluetooth;;{""type"":""flag"",""name"":""bluetooth"",""value"":1,""uiname"":""Bluetooth"",""descr":""Defines if the use of the bluetooth is allowed"",""state":1};1;integer
-2;bluetooth_tethering;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_tethering"",""value"":1,""uiname"":""Bluetooth tethering"",""descr":""Defines if the use of the bluetooth tethering is allowed"",""state":1};1;integer
-3;bluetooth_desktop_connectivity;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_desktop_connectivity"",""value"":1,""uiname"":""Bluetooth desktop connectivity"",""descr":""Defines if the use of the bluetooth desktop connectivity is allowed"",""state":1};1;integer
-4;bluetooth_pairing;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_pairing"",""value"":1,""uiname"":""Bluetooth pairing"",""descr":""Defines if the use of the bluetooth pairing is allowed"",""state":1};1;integer
-5;browser;;common;;{""type"":""flag"",""name"":""browser"",""value"":1,""uiname"":""Browser"",""descr":""Defines if the use of the browser is allowed"",""state":1};1;integer
-6;camera;;common;;{""type"":""flag"",""name"":""camera"",""value"":1,""uiname"":""Camera"",""descr":""Defines if the use of the camera is allowed"",""state":1};1;integer
-7;clipboard;;common;;{""type"":""flag"",""name"":""clipboard"",""value"":1,""uiname"":""Clipboard"",""descr":""Defines if the use of the clipboard is allowed"",""state":1};1;integer
-8;external_storage;;common;;{""type"":""flag"",""name"":""external_storage"",""value"":1,""uiname"":""External storage"",""descr":""Defines if the use of the external storage is allowed"",""state":1};1;integer
-9;location;;common;;{""type"":""flag"",""name"":""location"",""value"":1,""uiname"":""Geolocation"",""descr":""Defines if the use of the geolocation is allowed"",""state":1};1;integer
-10;messaging;;common;;{""type"":""select"",""name"":""messaging"",""items"":[{""key"":""sim1"",""value"":""1""},{""key"":""sim2"",""value"":""0""}],""uiname"":""Messaging"",""descr":""Defines if the use of the messaging is allowed"",""state":1};1;indexed
-11;microphone;;common;;{""type"":""flag"",""name"":""microphone"",""value"":1,""uiname"":""Microphone"",""descr":""Defines if the use of the microphone is allowed"",""state":1};1;integer
-12;popimap_email;;common;;{""type"":""flag"",""name"":""popimap_email"",""value"":1,""uiname"":""POP IMAP eMail"",""descr":""Defines if the use of the POP or IMAP email is allowed"",""state":1};1;integer
-13;usb_tethering;;common;;{""type"":""flag"",""name"":""usb_tethering"",""value"":1,""uiname"":""USB tethering"",""descr":""Defines if the use of the USB tethering is allowed"",""state":1};1;integer
-14;password_history;;password;;{""type"":""input-number"",""name"":""password_history"",""value"":100,""uiname"":""History"",""descr":""Defines if the password history is stated and if rules are defined"",""state":1};1;integer
-15;password_minimum_length;;password;;{""type"":""input-number"",""name"":""password_minimum_length"",""value"":6,""uiname"":""Minimum length"",""descr":""Defines the minimum password length"",""state":1};1;integer
-16;password_minimum_complexity;;password;;{""type"":""input-number"",""name"":""password_minimum_complexity"",""value"":2,""uiname"":""Minimum complexity"",""descr":""Defines the minimum password complexity"",""state":1};1;integer
-17;password_inactivity_timeout;;password;;{""type"":""input-number"",""name"":""password_inactivity_timeout"",""value"":30,""uiname"":""Inactivity timeout"",""descr":""Defines the inactivity time to lock"",""state":1};1;integer
-18;password_expired;;password;;{""type"":""input-number"",""name"":""password_expired"",""value"":90,""uiname"":""Expiration"",""descr":""Defines when the password will expire: 0 - never; positive number - number of days to expire"",""state":1};1;integer
-19;password_maximum_failure_count;;password;;{""type"":""input-number"",""name"":""password_maximum_failure_count"",""value"":10,""uiname"":""Maximum failed attempts"",""descr":""Defines how many times the user are allowed to type the wrong password before the device is blocked"",""state":1};1;integer
-20;password_numeric_sequences_length;;password;;{""type"":""input-number"",""name"":""password_numeric_sequences_length"",""value"":10,""uiname"":""Numeric sequences length"",""descr":""Defines the numeric sequences length"",""state":1};1;integer
-21;password_maximum_character_occurrences;;password;;{""type"":""input-number"",""name"":""password_maximum_character_occurrences"",""value"":10,""uiname"":""Maximum character occurrences"",""descr":""Defines the maximum character occurrences"",""state":1};1;integer
-22;password_quality;;password;;{""type"":""multiselect"",""name"":""password_quality"",""items"":[{""key"":""UNSPECIFIED"",""value"": 0},{""key"":""SIMPLE_PASSWORD"",""value"":1},{""key"":""SOMETHING"",""value"":1},{""key"":""ALPHABETIC"",""value"":1},{""key"":""ALPHANUMERIC"",""value"":0}],""uiname"":""Quality"",""descr":""Defines the password quality"",""state":1};1;integer
-23;wifi;;wifi;;{""type"":""flag"",""name"":""wifi"",""value"":1,""uiname"":""Wi-Fi"",""descr":""Defines if the use of the Wi-Fi is allowed"",""state":1};1;integer
-24;wifi_tethering;;wifi;;{""type"":""flag"",""name"":""wifi_tethering"",""value"":1,""uiname"":""Wi-Fi tethering"",""descr":""Defines if the use of the Wi-Fi tethering is allowed"",""state":1};1;integer
-25;wifi_profile_change;;wifi;;{""type"":""flag"",""name"":""wifi_profile_change"",""value"":1,""uiname"":""Wi-Fi profile change"",""descr":""Defines if the change of the Wi-Fi profile is allowed"",""state":1};1;integer
\ No newline at end of file
+id;name;descr;category;opt;defval;supported;mapping;uitype
+1;bluetooth;;bluetooth;;{""type"":""flag"",""name"":""bluetooth"",""value"":1,""uiname"":""Bluetooth"",""descr":""Defines if the use of the bluetooth is allowed"",""state":1};1;integer;flag
+2;bluetooth_tethering;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_tethering"",""value"":1,""uiname"":""Bluetooth tethering"",""descr":""Defines if the use of the bluetooth tethering is allowed"",""state":1};1;integer;flag
+3;bluetooth_desktop_connectivity;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_desktop_connectivity"",""value"":1,""uiname"":""Bluetooth desktop connectivity"",""descr":""Defines if the use of the bluetooth desktop connectivity is allowed"",""state":1};1;integer;flag
+4;bluetooth_pairing;;bluetooth;;{""type"":""flag"",""name"":""bluetooth_pairing"",""value"":1,""uiname"":""Bluetooth pairing"",""descr":""Defines if the use of the bluetooth pairing is allowed"",""state":1};1;integer;flag
+5;browser;;common;;{""type"":""flag"",""name"":""browser"",""value"":1,""uiname"":""Browser"",""descr":""Defines if the use of the browser is allowed"",""state":1};1;integer;flag
+6;camera;;common;;{""type"":""flag"",""name"":""camera"",""value"":1,""uiname"":""Camera"",""descr":""Defines if the use of the camera is allowed"",""state":1};1;integer;flag
+7;clipboard;;common;;{""type"":""flag"",""name"":""clipboard"",""value"":1,""uiname"":""Clipboard"",""descr":""Defines if the use of the clipboard is allowed"",""state":1};1;integer;flag
+8;external_storage;;common;;{""type"":""flag"",""name"":""external_storage"",""value"":1,""uiname"":""External storage"",""descr":""Defines if the use of the external storage is allowed"",""state":1};1;integer;flag
+9;location;;common;;{""type"":""flag"",""name"":""location"",""value"":1,""uiname"":""Geolocation"",""descr":""Defines if the use of the geolocation is allowed"",""state":1};1;integer;flag
+10;messaging;;common;;{""type"":""select"",""name"":""messaging"",""items"":[{""key"":""sim1"",""value"":""1""},{""key"":""sim2"",""value"":""0""}],""uiname"":""Messaging"",""descr":""Defines if the use of the messaging is allowed"",""state":1};1;indexed;select
+11;microphone;;common;;{""type"":""flag"",""name"":""microphone"",""value"":1,""uiname"":""Microphone"",""descr":""Defines if the use of the microphone is allowed"",""state":1};1;integer;flag
+12;popimap_email;;common;;{""type"":""flag"",""name"":""popimap_email"",""value"":1,""uiname"":""POP IMAP eMail"",""descr":""Defines if the use of the POP or IMAP email is allowed"",""state":1};1;integer;flag
+13;usb_tethering;;common;;{""type"":""flag"",""name"":""usb_tethering"",""value"":1,""uiname"":""USB tethering"",""descr":""Defines if the use of the USB tethering is allowed"",""state":1};1;integer;flag
+14;password_history;;password;;{""type"":""input-number"",""name"":""password_history"",""value"":100,""uiname"":""History"",""descr":""Defines if the password history is stated and if rules are defined"",""state":1};1;integer;input-number
+15;password_minimum_length;;password;;{""type"":""input-number"",""name"":""password_minimum_length"",""value"":6,""uiname"":""Minimum length"",""descr":""Defines the minimum password length"",""state":1};1;integer;input-number
+16;password_minimum_complexity;;password;;{""type"":""input-number"",""name"":""password_minimum_complexity"",""value"":2,""uiname"":""Minimum complexity"",""descr":""Defines the minimum password complexity"",""state":1};1;integer;input-number
+17;password_inactivity_timeout;;password;;{""type"":""input-number"",""name"":""password_inactivity_timeout"",""value"":30,""uiname"":""Inactivity timeout"",""descr":""Defines the inactivity time to lock"",""state":1};1;integer;input-number
+18;password_expired;;password;;{""type"":""input-number"",""name"":""password_expired"",""value"":90,""uiname"":""Expiration"",""descr":""Defines when the password will expire: 0 - never; positive number - number of days to expire"",""state":1};1;integer;input-number
+19;password_maximum_failure_count;;password;;{""type"":""input-number"",""name"":""password_maximum_failure_count"",""value"":10,""uiname"":""Maximum failed attempts"",""descr":""Defines how many times the user are allowed to type the wrong password before the device is blocked"",""state":1};1;integer;input-number
+20;password_numeric_sequences_length;;password;;{""type"":""input-number"",""name"":""password_numeric_sequences_length"",""value"":10,""uiname"":""Numeric sequences length"",""descr":""Defines the numeric sequences length"",""state":1};1;integer;input-number
+21;password_maximum_character_occurrences;;password;;{""type"":""input-number"",""name"":""password_maximum_character_occurrences"",""value"":10,""uiname"":""Maximum character occurrences"",""descr":""Defines the maximum character occurrences"",""state":1};1;integer;input-number
+22;password_quality;;password;;{""type"":""multiselect"",""name"":""password_quality"",""items"":[{""key"":""UNSPECIFIED"",""value"": 0},{""key"":""SIMPLE_PASSWORD"",""value"":1},{""key"":""SOMETHING"",""value"":1},{""key"":""ALPHABETIC"",""value"":1},{""key"":""ALPHANUMERIC"",""value"":0}],""uiname"":""Quality"",""descr":""Defines the password quality"",""state":1};1;integer;multiselect
+23;wifi;;wifi;;{""type"":""flag"",""name"":""wifi"",""value"":1,""uiname"":""Wi-Fi"",""descr":""Defines if the use of the Wi-Fi is allowed"",""state":1};1;integer;flag
+24;wifi_tethering;;wifi;;{""type"":""flag"",""name"":""wifi_tethering"",""value"":1,""uiname"":""Wi-Fi tethering"",""descr":""Defines if the use of the Wi-Fi tethering is allowed"",""state":1};1;integer;flag
+25;wifi_profile_change;;wifi;;{""type"":""flag"",""name"":""wifi_profile_change"",""value"":1,""uiname"":""Wi-Fi profile change"",""descr":""Defines if the change of the Wi-Fi profile is allowed"",""state":1};1;integer;flag
\ No newline at end of file