diff --git a/src/defs/openid.rs b/src/defs/openid.rs
index bb55838..bfcef24 100644
--- a/src/defs/openid.rs
+++ b/src/defs/openid.rs
@@ -30,6 +30,8 @@ pub struct OpenidClaims {
 	pub name: String,
 	pub owner: String,
 	pub email: String,
+	#[serde(default = "default_empty", rename(deserialize = "signupApplication"))]
+	pub signup_application: String,
 //	exp: i64,
 }
 #[derive(Default,Deserialize,Serialize,Debug,Clone)]
@@ -67,6 +69,7 @@ pub struct OpenidConf {
 	pub certificate: String,
 	pub org_name: String,
 	pub app_name: String,
+	pub signup_application: String,
 }
 
 pub struct OpenidCli {
diff --git a/src/users/openid.rs b/src/users/openid.rs
index 776c5b9..22a5bde 100644
--- a/src/users/openid.rs
+++ b/src/users/openid.rs
@@ -2,67 +2,50 @@ use serde::{Deserialize,Serialize};
 use sqlx::Row;
 use futures::TryStreamExt;
 use anyhow::{anyhow,Context, Result};
-use std::{
-    fmt,
-    collections::HashMap,
-};
-// use std::{
-//     // sync::Arc,
-//     fmt::Debug,
-//     // io::Write,
-//     // fs,
-//     // path::{Path, PathBuf},
-//     // io::{Error, ErrorKind},
-//     collections::HashMap,
-// };
-// use async_session::{MemoryStore, Session, SessionStore};
-//use tiitls_utils::logs::file;
-// use uuid::Uuid;
-//    SID_UI_FILE,
-//    UI_SETTINGS_FILE,
-//    SidSettings,
-//    Config as SessionsConfig, 
+use std::fmt;
 use std::num::ParseIntError;
 use crate::{
     users::{
         entries::{Entries,Entry},
-        UserData,
         UserStore,
-        UserStatus,
     },
-    USERS_TABLENAME,
+    OPENID_USERS_TABLENAME,
     tools::str_date_from_timestamp,
 };
-
 const DISPLAY_SEPARATOR: &str = "=";
 
-fn default_user_status() -> UserStatus {
-  UserStatus::default()
-}
-
 #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize,Default)]
-pub struct User {
+pub struct OpenidUser {
     pub id: i64,
-    pub name:     String,
-    pub fullname: String,
-    pub email:    String,
+    pub application: String,
+    pub appkey: String,
+    pub name: String,
+    pub userid: i64,
     pub description: String,
-    pub password: String,
-    pub otp_enabled: bool,
-    pub otp_verified: bool,
-    pub otp_base32: String,
-    pub otp_auth_url: String,
-    pub otp_defs: String,
-    pub roles: String,
     pub created:  String,
     pub lastaccess: String,
-    #[serde(default = "default_user_status")]
-    pub status: UserStatus,
-    pub items: String,
-    pub isadmin: bool,
 }
 
-impl fmt::Display for User {
+fn default_empty() -> String {
+    "".to_string()
+}
+#[derive(Default,Deserialize,Serialize,Debug,Clone)]
+pub struct OpenidUserData {
+    #[serde(default = "default_empty")]
+    pub id: String,
+    #[serde(default = "default_empty")]
+    pub name: String,
+    #[serde(default = "default_empty")]
+    pub application: String,
+    #[serde(default = "default_empty")]
+    pub appkey: String,
+    #[serde(default = "default_empty")]
+    pub userid: String,
+    #[serde(default = "default_empty")]
+    pub description: String,
+}
+
+impl fmt::Display for OpenidUser {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Write strictly the first element into the supplied output
         // stream: `f`. Returns `fmt::Result` which indicates whether the
@@ -72,108 +55,73 @@ impl fmt::Display for User {
         let content = format!(
             "ID{} {}
 Name{} {} 
-FullName{} {}
+Application{} {}
+AppKey {} {}
+UserId{} {}
 Description{} {}
-Email{} {}
-Password{} {}
-otp_enabled{} {}
-otp_verified{} {}
-otp_base32{} {}
-otp_auth_url{} {}
-otp_defs{} {}
-Roles{} {}
 Created{} {}
-Last access{} {}
-Status{} {}
-Items{} {}
-IsAdmin{} {}",
+Last access{} {}",
             sep, self.id,
-            sep, self.name, sep, self.fullname,
+            sep, self.name,
+            sep, self.application,
+            sep, self.appkey,
+            sep, self.userid,
             sep, self.description,
-            sep, self.email,
-            sep, self.password,
-            sep, self.otp_enabled,
-            sep, self.otp_verified,
-            sep, self.otp_base32,
-            sep, self.otp_auth_url,
-            sep, self.otp_defs,
-            sep, self.roles,
-            sep, self.created, sep, self.lastaccess,
-            sep, self.status,
-            sep, self.items,
-            sep, self.isadmin
+            sep, self.created,
+            sep, self.lastaccess,
         );
         write!(f, "{}", content)
     }
 }
 
-impl Entry for User {
-    fn from_line(line: &str) -> Result<User, ParseIntError> {
+impl Entry for OpenidUser {
+    fn from_line(line: &str) -> Result<OpenidUser, ParseIntError> {
         let parts: Vec<&str> = line.split(":").map(|part| part.trim()).collect();
-        Ok(User {
+        Ok(OpenidUser {
             id: parts[0].to_string().parse::<i64>().unwrap_or_default(),
             name: parts[1].to_string(),
-            fullname: parts[2].to_string(),
-            description: parts[3].to_string(),
-            email: parts[4].to_string(),
-            password: parts[5].to_string(),
-            otp_enabled: if parts[6] == "TRUE" { true } else { false},
-            otp_verified: if parts[7] == "TRUE" { true } else { false},
-            otp_base32: parts[8].to_string(),
-            otp_auth_url: parts[9].to_string(),
-            otp_defs: parts[10].to_string(),
-            roles: parts[11].to_string(),
-            created: parts[12].to_string(),
-            lastaccess: parts[13].to_string(),
-            status: UserStatus::from_str(&parts[14].to_string()),
-            items: parts[15].to_string(),
-            isadmin: if parts[16] == "TRUE" { true } else { false},
+            application: parts[2].to_string(),
+            appkey: parts[3].to_string(),
+            description: parts[4].to_string(),
+            userid: parts[5].to_string().parse::<i64>().unwrap_or_default(),
+            created: parts[6].to_string(),
+            lastaccess: parts[7].to_string(),
         })
     }
 }
-impl User {
+impl OpenidUser {
     pub async fn add(self, store: &UserStore) -> Result<i64> {
 
         match store {
             UserStore::Sql(pool) => {
                 let query_result = sqlx::query(
                     format!("INSERT INTO {} ( 
-                    name, fullname, email, description, password, otp_enabled, otp_verified,
-                    otp_base32,
-                    otp_auth_url,
-                    otp_defs,
-                    roles, created, lastaccess, status, items, isadmin
-                    ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", USERS_TABLENAME).as_str()
+                    name, application, appkey,
+                    userid,
+                    description,
+                    created, lastaccess
+                    ) VALUES ( ?, ?, ?, ?, ?, ?, ?)", OPENID_USERS_TABLENAME).as_str()
                 )
                 .bind(self.name)
-                .bind(self.fullname)
-                .bind(self.email)
+                .bind(self.application)
+                .bind(self.appkey)
+                .bind(self.userid)
                 .bind(self.description)
-                .bind(self.password)
-                .bind(self.otp_enabled)
-                .bind(self.otp_verified)
-                .bind(self.otp_base32)
-                .bind(self.otp_auth_url)
-                .bind(self.otp_defs)
-                .bind(self.roles)
                 .bind(self.created)
                 .bind(self.lastaccess)
-                .bind(format!("{}",self.status))
-                .bind(self.items)
-                .bind(self.isadmin)
                 .execute(pool).await?;
                 Ok(query_result.last_insert_id().unwrap_or_default())
             },
             UserStore::File(file_path) => {
                 // use itertools::Itertools;
                 // let entries: Vec<String> = concat(vec![
-                //     Entries::new(Path::new(&file_path)).map(|user: User|{ 
+                //     Entries::new(Path::new(&file_path)).map(|user: OpenidUser|{
                 //         user.line_format()
                 //     }).collect(),
                 //     vec![ self.line_format()]
                 // ]);
-                // Entries::<User>::write(Path::new(&file_path), &entries); 
-                let all: Vec<User> = Entries::new(&file_path).collect();
+                // Entries::<OpenidUser>::write(Path::new(&file_path), &entries);
+                let all: Vec<OpenidUser> = Entries::new(&file_path).collect();
                 let id = if all.len() > 0 {
                     all[all.len()-1].id + 1
                 } else {
@@ -181,32 +129,32 @@ impl User {
                 };
                 let mut new_user = self.to_owned();
                 new_user.id = id;
-                let entries: Entries<User> = Entries::new(&file_path);
+                let entries: Entries<OpenidUser> = Entries::new(&file_path);
                 match entries.append(new_user.line_format()) {
                     Ok(_) => Ok(id),
                     Err(e) => {
                         println!("Error add item to file: {}",e);
-                        Err(anyhow!("No data added")).context("User add")
+                        Err(anyhow!("No data added")).context("OpenidUser add")
                     }
                 }
             },
         }
     }
+    #[allow(dead_code)]
     pub async fn select(field: &str, value: &str, human: bool, store: &UserStore) -> Result<Self> {
         match store {
             UserStore::Sql(pool) => {
-                let query_str =  format!("SELECT * FROM {} WHERE {} = ? ", USERS_TABLENAME, field);
+                let query_str =  format!("SELECT * FROM {} WHERE '{}' = ?", OPENID_USERS_TABLENAME, field);
+                dbg!(&query_str);
                 let mut stream = sqlx::query(
                     &query_str
                 )
-                .bind(value)
-                //.map(|row: PgRow| {
-                //    map the row into a user-defined domain type
-                //})
-                .fetch(pool);
+                    .bind(value)
+                    //.map(|row: PgRow| {
+                    //    map the row into a user-defined domain type
+                    //})
+                    .fetch(pool);
                 if let Some(row) = stream.try_next().await? {
-                    let str_status: String = row.try_get("status")?;
-                    let status = UserStatus::from_str(&str_status);
                     let created = if human {
                         let created: String = row.try_get("created")?;
                         str_date_from_timestamp(&created)
@@ -222,49 +170,92 @@ impl User {
                     Ok(Self{
                         id: row.try_get("id")?,
                         name: row.try_get("name")?,
-                        fullname: row.try_get("fullname")?,
-                        email: row.try_get("email")?,
+                        application: row.try_get("application")?,
+                        appkey: row.try_get("appkey")?,
+                        userid: row.try_get("userid")?,
                         description: row.try_get("description")?,
-                        password: row.try_get("password")?,
-                        otp_enabled: row.try_get("otp_enabled")?,
-                        otp_verified: row.try_get("otp_verified")?,
-                        otp_base32: row.try_get("otp_base32")?,
-                        otp_auth_url: row.try_get("otp_auth_url")?,
-                        otp_defs: row.try_get("otp_defs")?,
-                        roles: row.try_get("roles")?,
                         created,
                         lastaccess,
-                        status,
-                        items: row.try_get("items")?,
-                        isadmin: row.try_get("isadmin")?,
                     })
                 } else {
-                    Err(anyhow!("No data found")).context("User select")
+                    Err(anyhow!("No data found")).context("OpenidUser select")
                 }
             },
             UserStore::File(file_path) => {
-                if let Some(user) = 
-                    Entries::<User>::new(&file_path).find(|it| 
+                if let Some(user) =
+                    Entries::<OpenidUser>::new(&file_path).find(|it|
                         match field {
                             "id" => it.id == value.parse::<i64>().unwrap_or_default(),
                             "name" => it.name == value,
-                            "fullname" => it.fullname == value,
-                            "email" => it.email == value,
-                            "description" => it.description == value,
-                            "otp_base32" => it.otp_base32 == value,
-                            "roles" => it.roles == value,
-                            "items" => it.items == value,
-                            "isadmin" => match value { 
-                                "TRUE" => it.isadmin,
-                                _ => !it.isadmin,
-                            },
+                            "application" => it.application == value,
+                            "appkey" => it.appkey == value,
+                            "userid" => it.userid == value.parse::<i64>().unwrap_or_default(),
                             _ => false,
                         }
                     )
                 {
                     Ok(user)
                 } else {
-                    Err(anyhow!("No data found")).context("User select")
+                    Err(anyhow!("No data found")).context("OpenidUser select")
+                }
+            },
+        }
+    }
+    pub async fn app_select(app: &str , field: &str, value: &str, human: bool, store: &UserStore) -> Result<Self> {
+        match store {
+            UserStore::Sql(pool) => {
+                let query_str =  format!("SELECT * FROM {} WHERE application = '{}' AND {} = ?", OPENID_USERS_TABLENAME, app, field);
+                let mut stream = sqlx::query(
+                    &query_str
+                )
+                .bind(value)
+                //.map(|row: PgRow| {
+                //    map the row into a user-defined domain type
+                //})
+                .fetch(pool);
+                if let Some(row) = stream.try_next().await? {
+                    let created = if human {
+                        let created: String = row.try_get("created")?;
+                        str_date_from_timestamp(&created)
+                    } else {
+                        row.try_get("created")?
+                    };
+                    let lastaccess = if human {
+                        let lastaccess: String = row.try_get("lastaccess")?;
+                        str_date_from_timestamp(&lastaccess)
+                    } else {
+                        row.try_get("lastaccess")?
+                    };
+                    Ok(Self{
+                        id: row.try_get("id")?,
+                        name: row.try_get("name")?,
+                        application: row.try_get("application")?,
+                        appkey: row.try_get("appkey")?,
+                        userid: row.try_get("userid")?,
+                        description: row.try_get("description")?,
+                        created,
+                        lastaccess,
+                    })
+                } else {
+                    Err(anyhow!("No data found")).context("OpenidUser select")
+                }
+            },
+            UserStore::File(file_path) => {
+                if let Some(user) = 
+                    Entries::<OpenidUser>::new(&file_path).find(|it|
+                        match field {
+                            "id" => it.id == value.parse::<i64>().unwrap_or_default(),
+                            "name" => it.name == value,
+                            "application" => it.application == app,
+                            "appkey" => it.application == value,
+                            "userid" => it.userid == value.parse::<i64>().unwrap_or_default(),
+                            _ => false,
+                        }
+                    )
+                {
+                    Ok(user)
+                } else {
+                    Err(anyhow!("No data found")).context("OpenidUser select")
                 }
             },
         }
@@ -273,7 +264,7 @@ impl User {
     pub async fn delete(id: i64, store: &UserStore) -> Result<bool> {
         match store {
             UserStore::Sql(pool) => {
-                let query_str = format!("DELETE FROM {} WHERE id = ?", USERS_TABLENAME);
+                let query_str = format!("DELETE FROM {} WHERE id = ?", OPENID_USERS_TABLENAME);
                 let query_result = sqlx::query(
                         &query_str
                     ) 
@@ -283,15 +274,15 @@ impl User {
             },
             UserStore::File(file_path) => {
                 let new_entries: Vec<String> = 
-                    Entries::<User>::new(&file_path).filter(|it| it.id != id).map(|user|
+                    Entries::<OpenidUser>::new(&file_path).filter(|it| it.id != id).map(|user|
                        user.line_format() 
                     ).collect();
-                let entries = Entries::<User>::new(&file_path);
+                let entries = Entries::<OpenidUser>::new(&file_path);
                 match entries.write(&new_entries) {
                     Ok(_) => Ok(true),
                     Err(e) => {
                         println!("Error data delete '{}': {}", id, e);
-                        Err(anyhow!("No data delete").context("User delete"))
+                        Err(anyhow!("No data delete").context("OpenidUser delete"))
                     }
                 }
             },
@@ -300,56 +291,44 @@ impl User {
     pub async fn update(self, store: &UserStore) -> anyhow::Result<bool> {
         match store {
             UserStore::Sql(pool) => {
-                let query_str = format!("UPDATE {} SET name = ?, fullname = ?, 
-                    email = ?, description = ?, password = ?,
-                    otp_enabled = ?, otp_verified = ?,
-                    otp_base32 = ?, otp_auth_url = ?,
-                    otp_defs = ?,
-                    roles = ?,
-                    created = ?, lastaccess = ?,
-                    status = ?,
-                    items = ?,
-                    isadmin = ? 
+                let query_str = format!("UPDATE {} SET name = ?,
+                    application = ?,
+                    appkey = ?,
+                    userid = ?,
+                    description = ?,
+                    created = ?,
+                    lastaccess = ?
                  WHERE id = ? ",
-                    USERS_TABLENAME
+                    OPENID_USERS_TABLENAME
                 );
                 let query_result = sqlx::query(
                         &query_str
                     ) 
                     .bind(self.name)
-                    .bind(self.fullname)
-                    .bind(self.email)
+                    .bind(self.application)
+                    .bind(self.appkey)
+                    .bind(self.userid)
                     .bind(self.description)
-                    .bind(self.password)
-                    .bind(self.otp_enabled)
-                    .bind(self.otp_verified)
-                    .bind(self.otp_base32)
-                    .bind(self.otp_auth_url)
-                    .bind(self.otp_defs)
-                    .bind(self.roles)
                     .bind(self.created)
                     .bind(self.lastaccess)
-                    .bind(format!("{}",self.status))
-                    .bind(self.items)
-                    .bind(self.isadmin)
                     .bind(self.id)
                     .execute(pool).await?;
                  Ok(query_result.rows_affected() > 0)
             },
             UserStore::File(file_path) => {
-                let new_entries: Vec<String> = Entries::new(&file_path).map(|user: User|{ 
+                let new_entries: Vec<String> = Entries::new(&file_path).map(|user: OpenidUser|{
                     if user.id == self.id {
                         self.to_owned().line_format()
                     } else {
                         user.line_format()
                     }
                 }).collect();
-                let entries = Entries::<User>::new(&file_path);
+                let entries = Entries::<OpenidUser>::new(&file_path);
                 match entries.write(&new_entries) {
                     Ok(_) => Ok(true),
                     Err(e) => {
                         println!("Error data update '{}': {}", self.id, e);
-                        Err(anyhow!("No data updated").context("User update"))
+                        Err(anyhow!("No data updated").context("OpenidUser update"))
                     }
                 }
             },
@@ -357,34 +336,25 @@ impl User {
     }
     pub fn show(&self, sep: &str) {
         let content = if sep.is_empty() {
-            format!( "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
+            format!( "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                 self.id,
-                self.name, self.fullname,
+                self.name,
+                self.application,
+                self.appkey,
+                self.userid,
                 self.description,
-                self.email,
-                self.password,
-                self.otp_enabled,
-                self.otp_verified,
-                self.otp_base32,
-                self.otp_auth_url,
-                self.otp_defs,
-                self.roles,
                 self.created,
                 self.lastaccess,
-                self.status,
-                self.items,
-                self.isadmin
             )
         } else {
-            format!("{}",&self).replace(DISPLAY_SEPARATOR, sep)
+            format!("{}",self).replace(DISPLAY_SEPARATOR, sep)
         };
         println!("{}\n_____________________________",content);
     }
-    pub async fn list(store: &UserStore, human: bool, show: bool, sep: &str) -> anyhow::Result<Vec<User>> {
-        let mut usrs: Vec<User> = Vec::new();
+    pub async fn users_list( query_str: &str, store: &UserStore, human: bool, show: bool, sep: &str) -> anyhow::Result<Vec<OpenidUser>> {
+        let mut usrs: Vec<OpenidUser> = Vec::new();
         match store {
             UserStore::Sql(pool) => {
-                let query_str =  format!("SELECT * FROM {}", USERS_TABLENAME);
                 let mut stream = sqlx::query(
                     &query_str
                 )
@@ -393,8 +363,6 @@ impl User {
                 //})
                 .fetch(pool);
                 while let Some(row) = stream.try_next().await? {
-                    let str_status: String = row.try_get("status")?;
-                    let status = UserStatus::from_str(&str_status);
                     let created = if human {
                         let created: String = row.try_get("created")?;
                         str_date_from_timestamp(&created)
@@ -410,21 +378,12 @@ impl User {
                     let user = Self{
                         id: row.try_get("id")?,
                         name: row.try_get("name")?,
-                        fullname: row.try_get("fullname")?,
-                        email: row.try_get("email")?,
+                        application: row.try_get("application")?,
+                        appkey: row.try_get("appkey")?,
+                        userid: row.try_get("userid")?,
                         description: row.try_get("description")?,
-                        password: row.try_get("password")?,
-                        otp_enabled: row.try_get("otp_enabled")?,
-                        otp_verified: row.try_get("otp_verified")?,
-                        otp_base32: row.try_get("otp_base32")?,
-                        otp_auth_url: row.try_get("otp_auth_url")?,
-                        otp_defs: row.try_get("otp_defs")?,
-                        roles: row.try_get("roles")?,
                         created,
                         lastaccess,
-                        status,
-                        items: row.try_get("items")?,
-                        isadmin: row.try_get("isadmin")?,
                     };
                     if show { user.show(sep); }
                     usrs.push(user);
@@ -432,200 +391,106 @@ impl User {
                 Ok(usrs)
             },
             UserStore::File(file_path) => {
-                let all: Vec<User> = Entries::new(&file_path).collect();
+                let all: Vec<OpenidUser> = Entries::new(&file_path).collect();
                 if show {
                     for user in all.to_owned() { if show { user.show(sep); } }
                 }
                 Ok(all)
             },
-            // UserStore::None => Err(anyhow!("No store set")).context("Users list"),
+            // UserStore::None => Err(anyhow!("No store set")).context("OpenidUsers list"),
         }
-    }       
+    }
+    #[allow(dead_code)]
+    pub async fn list(store: &UserStore, human: bool, show: bool, sep: &str) -> anyhow::Result<Vec<OpenidUser>> {
+        OpenidUser::users_list(
+            &format!("SELECT * FROM {}", OPENID_USERS_TABLENAME),
+            store, human, show, sep
+        ).await
+    }
+    pub async fn list_selection(field: &str, value: &str, store: &UserStore, human: bool, show: bool, sep: &str) -> anyhow::Result<Vec<OpenidUser>> {
+        OpenidUser::users_list(
+           &format!("SELECT * FROM {} WHERE {} = '{}'", OPENID_USERS_TABLENAME, &field, &value),
+            store, human, show, sep
+        ).await
+    }
+    #[allow(dead_code)]
     pub async fn count(store: &UserStore) -> anyhow::Result<i64> {
         match store {
             UserStore::Sql(pool) => {
-
-                let query_str =  format!("SELECT count(*) as total FROM {}", USERS_TABLENAME);
+                let query_str =  format!("SELECT count(*) as total FROM {}", OPENID_USERS_TABLENAME);
                 let row = sqlx::query(
                     &query_str
                 )
                 .fetch_one(pool).await?;
-
                 let total: i64 = row.try_get("total")?;
                 Ok(total)
             },
             UserStore::File(file_path) => {
-                let all: Vec<User> = Entries::new(&file_path).collect();
+                let all: Vec<OpenidUser> = Entries::new(&file_path).collect();
                 Ok(all.len() as i64)
             },
         }
     }
     fn line_format(self) -> String {
-        format!( "{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
+        format!( "{}:{}:{}:{}:{}:{}:{}:{}",
             self.id,
-            self.name, self.fullname,
+            self.name,
+            self.application,
+            self.appkey,
             self.description,
-            self.email,
-            self.password,
-            self.otp_enabled,
-            self.otp_verified,
-            self.otp_base32,
-            self.otp_auth_url,
-            self.otp_defs,
-            self.roles,
-            self.created, self.lastaccess,
-            self.status,
-            self.items,
-            self.isadmin
+            self.userid,
+            self.created,
+            self.lastaccess,
         )
     }
-    pub fn hash_items(items: &str) -> HashMap<String,String> {
-        if items.is_empty() {
-            HashMap::new()
-        } else {
-            serde_json::from_str(items).unwrap_or_else(|e|{
-                println!("Error to convert user items to json: {}",e);
-                HashMap::new()
-            })
-        }
-    }
-    pub fn items(&self) -> HashMap<String,String> {
-        Self::hash_items(&self.items)
-    }
-    pub fn json_items(items: HashMap<String,String>) -> String {
-        serde_json::to_string(&items).unwrap_or_else(|e|{
-            println!("Error to convert user items to string: {}",e);
-            String::from("")
-        })
-    }
-    pub fn from_data(&mut self, user_data: UserData) {
+    /*
+    pub fn from_data(&mut self, user_data: OpenidUserData) {
         if !user_data.name.is_empty() {
             self.name = user_data.name.to_owned();
         }
-        if !user_data.fullname.is_empty() {
-            self.fullname = user_data.fullname.to_owned();
+        if !user_data.application.is_empty() {
+            self.application = user_data.application.to_owned();
         }
         if !user_data.description.is_empty() {
             self.description = user_data.description.to_owned();
         }
-        if !user_data.email.is_empty() {
-            self.email = user_data.email.to_owned();
-        }
-        if !user_data.otp_code.is_empty() {
-            self.otp_base32 = user_data.otp_code.to_owned();
-        }
-        if !user_data.otp_url.is_empty() {
-            self.otp_auth_url = user_data.otp_url.to_owned();
-        }
-        if !user_data.roles.is_empty() {
-            self.roles = user_data.roles.to_owned();
-        }
-        if !user_data.items.is_empty() {
-            let mut items_hash = self.items();
-            for (key,val) in user_data.items {
-                items_hash.insert(key,val);
-            }
-            self.items = Self::json_items(items_hash);
-        }
     }
-    pub fn disable_totp(&mut self) {
-        self.otp_base32 = String::from("");
-        self.otp_auth_url = String::from("");
-        self.otp_defs = String::from("");
-        self.otp_verified =  false;
-        self.otp_enabled =  false;
-    }
-    pub fn from_user(&mut self, new_user: User) {
+    pub fn from_user(&mut self, new_user: OpenidUser) {
         if !new_user.name.is_empty() {
             self.name = new_user.name.to_owned();
         }
-        if !new_user.fullname.is_empty() {
-            self.fullname = new_user.fullname.to_owned();
+        if !new_user.application.is_empty() {
+            self.application = new_user.application.to_owned();
         }
         if !new_user.description.is_empty() {
             self.description = new_user.description.to_owned();
         }
-        if !new_user.email.is_empty() {
-            self.email = new_user.email.to_owned();
-        }
-        if !new_user.password.is_empty() {
-            self.password = new_user.password.to_owned();
-        }
-        if new_user.otp_enabled  {
-            self.disable_totp();
-        } else {
-            if !new_user.otp_base32.is_empty() {
-                self.otp_base32 = new_user.otp_base32.to_owned();
-            }
-            if !new_user.otp_auth_url.is_empty() {
-                self.otp_auth_url = new_user.otp_auth_url.to_owned();
-            }
-            if !new_user.otp_defs.is_empty() {
-                self.otp_defs = new_user.otp_defs.to_owned();
-            }
-            self.otp_verified =  new_user.otp_verified;
-        }
-        if !new_user.roles.is_empty() {
-            self.roles = new_user.roles.to_owned();
-        }
-        if !new_user.items.is_empty() {
-            self.items = new_user.items.to_owned();
-        }
-        if new_user.status != self.status {
-            self.status = new_user.status.to_owned();
-        }
     }
     pub fn session_data(&self) -> String {
-        format!("{}|{}|{}|{}|{}|{}|{}",
+        format!("{}|{}|{}|{}|{}",
             &self.id,
             &self.name,
-            &self.email,
-            &self.roles,
-            &self.items,
-            &self.isadmin,
-            &self.status
+            &self.application,
+            &self.appkey,
+            &self.userid
         )
     }
-    pub fn estimate_password(word: &str) -> String  {
-         match zxcvbn::zxcvbn(word, &[]) {
-            Ok(estimate) => {
-                if let Some(feedback) = estimate.feedback() {
-                    let arr_suggestions: Vec<String> = feedback.suggestions().iter().map(|s| format!("{}",s)).collect();
-                    let suggestions = arr_suggestions.join("\n");
-                    if let Some(warning) = feedback.warning() {
-                        let warning = format!("{}", warning);
-                        format!("{}|{}|{}",estimate.score(),suggestions,warning)
-                    } else {
-                        format!("{}|{}|",estimate.score(),suggestions)
-                    }
-                } else {
-                    format!("{}||",estimate.score())
-                }
-            },
-            Err(e) => {
-                println!("Error password strength estimator: {}", e);
-                String::from("-1|||")
+    */
+    pub async fn sync_ids(userid: &str, open_ids: &str, store: &UserStore) {
+        let openid_sel = OpenidUser::list_selection(
+            "userid", userid, store, true,false, "|"
+        ).await.unwrap_or_else(|e| {
+            println!("Error list selection {}: {}", &userid, e);
+            Vec::new()
+        });
+        let new_open_ids: Vec<String> = open_ids.split(",").map(|s| s.to_string()).collect();
+        for itm in openid_sel {
+            if new_open_ids.len() == 0  || ! new_open_ids.contains(&itm.appkey) {
+                let _res = OpenidUser::delete(itm.id, &store).await.unwrap_or_else(|e| {
+                    println!("Error delete {}: {}",&itm.appkey,e);
+                    false
+                });
             }
         }
     }
-    pub fn password_score(word: &str) -> u8 {
-         match zxcvbn::zxcvbn(word, &[]) {
-            Ok(estimate) => {
-                estimate.score()
-            },
-            Err(e) => {
-                println!("Error password strength estimator: {}", e);
-                0
-            }
-        }
-    }
-    #[allow(dead_code)]
-    pub fn has_auth_role(&self, auth_roles: Vec<String>) -> bool {
-        for role in auth_roles {
-            if self.roles.contains(&role) {
-                return true;
-            }
-        }
-        return false;
-    }
 }
\ No newline at end of file