Пример #1
0
 public long GetUserSyncToken(User user)
 {
     using (SQLiteConnection conn = new SQLiteConnection(String.Format("Data Source={0};Version=3;", "DB/management.db3")))
     {
         conn.Open();
         using (SQLiteCommand cmd = conn.CreateCommand())
         {
             cmd.CommandText = "SELECT synctoken FROM users_updates WHERE iduser=$iduser";
             cmd.Parameters.AddWithValue("iduser",user.Id);
             long stoken = (long)cmd.ExecuteScalar();
             return stoken;
         }
     }
 }
Пример #2
0
        // Da usare solo lato server non esporla al protocollo di rete.
        // TODO cache memoria
        public User LoginT(string username, string accessToken)
        {
            try
            {
                // Check iniziali su lunghezze minime e null checks
                // TODO

                // TODO: migliorare con cache in memoria degli utenti loggati.

                long id;
                // ------------------ NOTA SUL LOCK ------------------
                // In questo caso non tocchiamo il DB in scrittura, ma solo in lettura. Sono possibili corse critiche con letture spurie.
                // In realtà per noi non è un problema, perchè al prossimo tentativo di SYNC verrà richiesto il token all'utente e ne verrà
                // controllata la validità.

                // Eventuali eccezioni qui
                SQLiteConnection conn;
                using (conn = new SQLiteConnection("Data Source=DB/management.db3;Version=3;"))
                {
                    conn.Open();

                    // Seleziona da database tramite username e token
                    using (SQLiteCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "SELECT id, username, accesstoken, expire FROM users WHERE username=$username and accesstoken=$accesstoken";
                        cmd.Parameters.AddWithValue("username", username);
                        cmd.Parameters.AddWithValue("accesstoken", accessToken);
                        using (var r = cmd.ExecuteReader())
                        {
                            // Se non ho risultati, il login è errato
                            if (!r.Read())
                                throw new UserLoginException("Token non valido o non legato all'utente specificato.");

                            id = r.GetInt64(0);

                            // Se l'access token è nullo, il login è invalido.
                            if (r.IsDBNull(2))
                                throw new UserLoginException("Token non valido o non legato all'utente specificato.");
                            else
                            {
                                // Controllo se il token è scaduto.
                                if (r.IsDBNull(3) || DateTime.Parse(r.GetString(3)) < DateTime.Now)
                                    throw new UserLoginException("Token scaduto. Si prega di rieffettuare il login");
                            }
                        }

                        // Se esiste già un'altra connessione relativa allo stesso utente, ritorna il medesimo oggetto User
                        // in modo da garantire sincronia. Nota: solo questo oggetto può scrivere su _connectedUsers, quindi, avendo già il lock qui,
                        // non devo riacquisirlo. In altre parole posso manipolare in lettura e scrittura la mappa solo da questo metodo.
                        // Ergo sono già sincronizzato.
                        if (!_connctedUsers.ContainsKey(id))
                        {
                            User u = new User(id, username);
                            _connctedUsers.Add(id, u);
                        }

                        // Incrementa il reference counting per l'oggetto che ritorniamo
                        User logged = _connctedUsers[id];
                        //Il reference counting non vale per gli utenti che usano il token
                        //logged.IncConnections();
                        return logged;
                    }

                }
            }
            catch (Exception e)
            {
                throw new UserLoginException(e.Message);
            }
        }
Пример #3
0
        public void Logout(User user)
        {
            try
            {
                // ------------------ NOTA SUL LOCK ------------------
                // In questo caso non tocchiamo il DB in scrittura, ma solo in lettura. Sono possibili corse critiche con letture spurie.
                // In realtà per noi non è un problema, perchè al prossimo tentativo di SYNC verrà richiesto il token all'utente e ne verrà
                // controllata la validità.

                // Eventuali eccezioni qui
                SQLiteConnection conn;
                using (conn = new SQLiteConnection("Data Source=DB/management.db3;Version=3;"))
                {
                    conn.Open();

                    // Seleziona da database tramite username e token
                    using (SQLiteCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "UPDATE users SET accesstoken=NULL,expire=DATE() where id=$id";
                        cmd.Parameters.AddWithValue("id", user.Id);
                        if (cmd.ExecuteNonQuery() != 1)
                            throw new UserLogoutException("Non è stata aggiornata alcuna riga sul db. L'utente potrebbe essere invalido o già sloggato.");
                        // Se l'utente che sta effettuando logout è nella lista dello user manager, eliminiamo la entry corrispondente.
                        // in questo modo tutte le altre connessioni avranno la cache invalidata.
                        if (_connctedUsers.ContainsKey(user.Id))
                        {
                            _connctedUsers.Remove(user.Id);
                        }
                    }

                }
            }
            catch (Exception e)
            {
                throw new UserLoginException(e.Message);
            }
        }
Пример #4
0
 public void RemoveConnectedUser(User user)
 {
     lock (this) {
         if (_connctedUsers.ContainsKey(user.Id))
             _connctedUsers.Remove(user.Id);
     }
 }
Пример #5
0
        public User LoginUP(string username,string password, out string accesstoken, out DateTime expirationdate)
        {
            try
            {
                // Check iniziali su lunghezze minime e null checks
                //TODO
                long id;
                // ******************* user manager è l'unico entrypoint per modificate la tabella users ***********
                lock (this)
                {
                    SQLiteConnection conn;
                    using (conn = new SQLiteConnection("Data Source=DB/management.db3;Version=3;"))
                    {
                        conn.Open();
                        // Abbiamo bisogno di una transazione perchè dobbiamo aggiornare l'ultima data di login solo se questo va a buon fine.
                        using (SQLiteTransaction tr = conn.BeginTransaction())
                        {
                            try
                            {
                                // Seleziona da database l'utente in base a username e password
                                using (SQLiteCommand cmd = conn.CreateCommand())
                                {
                                    // Hasha la password
                                    string encpwd = Hash(password);
                                    cmd.CommandText = "SELECT id, username, accesstoken, expire FROM users WHERE username=$username and password=$password";
                                    cmd.Parameters.AddWithValue("username", username);
                                    cmd.Parameters.AddWithValue("password", encpwd);
                                    using (var r = cmd.ExecuteReader())
                                    {
                                        // Se non ho risultati, il login è errato
                                        if (!r.Read())
                                            throw new UserLoginException("Combinazione username/password non valida.");

                                        id = r.GetInt64(0);

                                        // at può essere nullo nel caso in cui questo sia il primo login. In tal caso, devo generare un token
                                        if (r.IsDBNull(2))
                                        {
                                            accesstoken = Guid.NewGuid().ToString();
                                        }
                                        else {
                                            // Se il token esiste, controlla che non sia scaduto.
                                            if (r.IsDBNull(3) || DateTime.Parse(r.GetString(3))<DateTime.Now)
                                                accesstoken = Guid.NewGuid().ToString();

                                            accesstoken = r.GetString(2);
                                        }
                                    }
                                    // A questo punto prolunghiamo la validit dell'access token
                                    expirationdate = DateTime.Now;
                                    expirationdate = expirationdate.Add(TOKEN_VALIDITY_SPAN);

                                    // Aggiorno i dati su db
                                    cmd.Parameters.Clear();
                                    cmd.CommandText = "UPDATE users SET accesstoken=$accesstoken, lastlogin=DATE(), expire=$expire WHERE id=$id";
                                    cmd.Parameters.AddWithValue("accesstoken", accesstoken);
                                    cmd.Parameters.AddWithValue("expire", expirationdate.ToString("yyyy-MM-dd HH:mm:ss")); //todo check this
                                    cmd.Parameters.AddWithValue("id", id);

                                    int res = cmd.ExecuteNonQuery();
                                    if (res != 1)
                                        throw new UserLoginException("Errore durante l'aggiornamento dati nel database.");

                                    // Se tutto è andato bene, effettua il commit.
                                    tr.Commit();

                                    // Se esiste già un'altra connessione relativa allo stesso utente, ritorna il medesimo oggetto User
                                    // in modo da garantire sincronia. Nota: solo questo oggetto può scrivere su _connectedUsers, quindi, avendo già il lock qui,
                                    // non devo riacquisirlo. In altre parole posso manipolare in lettura e scrittura la mappa solo da questo metodo.
                                    // Ergo sono già sincronizzato.
                                    if (!_connctedUsers.ContainsKey(id)) {
                                        User u = new User(id, username);
                                        _connctedUsers.Add(id,u);
                                    }

                                    // Incrementa il reference counting per l'oggetto che ritorniamo
                                    User logged = _connctedUsers[id];
                                    //Il reference counting non vale per gli utenti che usano il token
                                    //logged.IncConnections();
                                    return logged;

                                }
                            }
                            catch (Exception e)
                            {
                                // Errore generico: rollback
                                tr.Rollback();
                                // E lascialo gestire allo scope più alto.
                                throw e;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new UserLoginException(e.Message);
            }
        }