/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-2014, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include "users.h" #include "sessionmanager.h" #include "plugin.h" namespace Winix { Users::Users() { how_many_logged = 0; // !! CHECK ME may it should be moved to Clear() method? Clear(); } void Users::SetCur(Cur * pcur) { cur = pcur; } void Users::SetSessionManager(SessionManager * sm) { session_manager = sm; } void Users::Clear() { table.Clear(); } void Users::ReadUsers(Db * db) { Clear(); db->GetUsers(table); } bool Users::AddUser(const User & user) { Table::Iterator i = table.PushBack(user); return (i != table.End()); } bool Users::IsUser(const std::wstring & name) { return table.Is(name); } User * Users::GetUser(long user_id) { Table::Iterator i = table.FindId(user_id); if( i == table.End() ) return 0; return &(*i); } User * Users::GetUser(const std::wstring & name) { Table::Iterator i = table.FindName(name); if( i == table.End() ) return 0; return &(*i); } long Users::GetUserId(const std::wstring & name) { User * puser = GetUser(name); if( !puser ) return -1; return puser->id; } Users::Iterator Users::Begin() { return table.Begin(); } Users::Iterator Users::End() { return table.End(); } Users::SizeType Users::Size() { return table.Size(); } bool Users::Remove(long user_id) { bool result = false; User * puser = GetUser(user_id); if( puser ) { LogoutUser(user_id); plugin.Call(WINIX_PREPARE_TO_REMOVE_USER, puser); result = table.Remove(user_id); if( result ) plugin.Call(WINIX_USER_REMOVED, user_id); } return result; } // private bool Users::LoginUserCheckSession(bool use_ses_log) { if( !cur->session ) return false; if( cur->session->id == 0 ) { log << log1 << "Users: I cannot login a user on a temporary session" << logend; if( use_ses_log ) slog << logerror << T(L"service_unavailable") << logend; return false; } return true; } // private User * Users::LoginUserCheckStatus(long user_id, bool use_ses_log) { User * puser = GetUser(user_id); if( !puser ) { log << log1 << "Users: user id: " << user_id << " is not in system.users table" << logend; if( use_ses_log ) slog << logerror << T(L"service_unavailable") << logend; return 0; } if( puser->status != WINIX_ACCOUNT_READY ) { log << log1 << "Users: user id: " << user_id << " is not ready for logging in (status: " << puser->status << ")" << logend; if( use_ses_log ) { if( puser->status == WINIX_ACCOUNT_NOT_ACTIVATED ) slog << logerror << T(L"account_not_activated") << logend; else if( puser->status == WINIX_ACCOUNT_SUSPENDED ) slog << logerror << T(L"account_suspended") << logend; else if( puser->status == WINIX_ACCOUNT_BLOCKED ) slog << logerror << T(L"account_banned") << logend; } return 0; } return puser; } bool Users::LoginUser(long user_id, bool remember_me, bool use_ses_log) { if( !LoginUserCheckSession(use_ses_log) ) return false; User * puser = LoginUserCheckStatus(user_id, use_ses_log); if( !puser ) return false; PluginRes res = plugin.Call(WINIX_PREPARE_USER_TO_LOGIN, puser); if( res.res_false > 0 ) { log << log3 << "Users: login prevented by a plugin" << logend; return false; } if( cur->session->puser ) LogoutCurrentUser(); cur->session->puser = puser; cur->session->spam_score = 0; cur->session->remember_me = remember_me; // change session id before last.UserLogin() if( !cur->session->new_session ) session_manager->ChangeSessionId(cur->session->id); last.UserLogin(user_id, cur->session->puser->name, cur->request->ip, cur->session->id); how_many_logged += 1; log << log2 << "Users: user " << cur->session->puser->name << " (id: " << user_id << ") logged" << logend; plugin.Call(WINIX_USER_LOGGED); return true; } size_t Users::LogoutUser(long user_id) { size_t how_many = 0; User * puser = GetUser(user_id); if( puser ) { log << log2 << "Users: logging out user " << puser->name << ", id: " << puser->id << " from all sessions" << logend; // WINIX_PREPARE_USER_TO_LOGOUT will be sent by MarkAllSessionsToRemove() how_many = session_manager->MarkAllSessionsToRemove(user_id); how_many_logged -= how_many; if( how_many ) log << log3 << "Users: " << how_many << " user(s) were logged out" << logend; } return how_many; } void Users::LogoutCurrentUser() { if( !cur->session || !cur->session->puser ) return; log << log2 << "Users: user " << cur->session->puser->name << ", id: " << cur->session->puser->id << " logged out" << logend; plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, cur->session->puser); last.UserLogout(cur->session->puser->id, cur->session->id); if( how_many_logged > 0 ) // for safety how_many_logged -= 1; cur->session->puser = 0; cur->session->remember_me = false; } void Users::IncrementLoggedUsers() { how_many_logged += 1; } long Users::HowManyLogged() { return how_many_logged; } } // namespace Winix