winix/winixd/db/db.cpp

414 lines
9.8 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2021, 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 "db.h"
#include "core/log.h"
#include "core/misc.h"
namespace Winix
{
//void Db::PostgreSQLsmallerThan10(bool is_smaller_than_10)
//{
// is_postgresql_smaller_than_10 = is_smaller_than_10;
//
// if( is_postgresql_smaller_than_10 )
// {
// postgrsql_row_statement.clear();
// }
// else
// {
// postgrsql_row_statement = L"ROW";
// }
//}
/*
bool Db::GetUserPass(const std::wstring & login, long & user_id, UserPass & up)
{
PGresult * r = 0;
bool user_ok = false;
user_id = -1;
try
{
query.Clear();
query << R("select id, has_pass, password, pass_encrypted, pass_type, pass_hash_salted from core.user where login=")
<< login
<< R(";");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(r);
if( rows == 0 )
throw Error(WINIX_ERR_DB_INCORRECT_LOGIN);
if( rows > 1 )
{
log << log1 << "Db: there is more than one user: " << login << logend;
throw Error(WINIX_ERR_DB_MORE_THAN_ONE_LOGIN);
}
int cuser_id = AssertColumn(r, "id");
int chas_pass = AssertColumn(r, "has_pass");
int cpass_type = AssertColumn(r, "pass_type");
int csalted = AssertColumn(r, "pass_hash_salted");
int cpassword = AssertColumn(r, "password");
int cpass_encrypted = AssertColumn(r, "pass_encrypted");
user_ok = true;
user_id = AssertValueLong(r, 0, cuser_id);
up.has_pass = AssertValueBool(r, 0, chas_pass);
up.pass_type = AssertValueInt(r, 0, cpass_type);
up.pass_hash_salted = AssertValueBool(r, 0, csalted);
AssertValueWide(r, 0, cpassword, up.pass);
AssertValueBin(r, 0, cpass_encrypted, up.pass_encrypted);
}
catch(const Error &)
{
}
ClearResult(r);
return user_ok;
}
Error Db::AddUser(User & user, const UserPass & up)
{
PGresult * r = 0;
Error status = WINIX_ERR_OK;
try
{
query.Clear();
query << R("insert into core.user (login, has_pass, password, pass_encrypted, super_user, email,"
"notify, pass_type, pass_hash_salted, env, aenv, status, locale_id, time_zone_id) values (")
<< user.name
<< up.has_pass;
// for safety we put up.pass only if there is not an encrypted version
// someone could have forgotten to clear up.pass
if( up.pass_encrypted.empty() )
query << up.pass;
else
query << "";
query.EPutBin(up.pass_encrypted);
query << user.super_user
<< user.email
<< user.notify
<< up.pass_type
<< up.pass_hash_salted
<< user.env
<< user.aenv
<< user.status
<< user.locale_id
<< user.time_zone_id
<< R(");");
r = AssertQuery(query);
AssertResult(r, PGRES_COMMAND_OK);
user.id = AssertCurrval("core.user_id_seq");
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
Error Db::ChangeUserPass(long user_id, const UserPass & up)
{
query.Clear();
query << R("update core.user set(has_pass, password, pass_encrypted,"
"pass_type, pass_hash_salted) = ") << R(postgrsql_row_statement) << R("(")
<< up.has_pass;
// for safety
if( up.pass_encrypted.empty() )
query << up.pass;
else
query << "";
query.EPutBin(up.pass_encrypted);
query << up.pass_type
<< up.pass_hash_salted
<< R(") where id=")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserEnv(long user_id, const PT::Space & space)
{
query.Clear();
query << R("update core.user set(env) = ") << R(postgrsql_row_statement) << R("(")
<< space
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserAdminEnv(long user_id, const PT::Space & space)
{
query.Clear();
query << R("update core.user set(aenv) = ") << R(postgrsql_row_statement) << R("(")
<< space
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserStatus(long user_id, int status)
{
query.Clear();
query << R("update core.user set(status) = ") << R(postgrsql_row_statement) << R("(")
<< status
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserEmail(long user_id, const std::wstring & email)
{
query.Clear();
query << R("update core.user set(email) = ") << R(postgrsql_row_statement) << R("(")
<< email
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserLocale(long user_id, size_t locale_id)
{
query.Clear();
query << R("update core.user set(locale_id) = ") << R(postgrsql_row_statement) << R("(")
<< locale_id
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserTimeZone(long user_id, size_t time_zone_id)
{
query.Clear();
query << R("update core.user set(time_zone_id) = ") << R(postgrsql_row_statement) << R("(")
<< time_zone_id
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::RemoveUser(long user_id)
{
query.Clear();
query << R("delete from core.user where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
void Db::GetUsers(UGContainer<User> & user_tab)
{
PGresult * r = 0;
try
{
query.Clear();
query << R("select id, login, super_user, group_id, email, notify,"
" env, aenv, status, locale_id, time_zone_id"
" from core.user left outer join core.group_mem on"
" core.user.id = core.group_mem.user_id order by id asc;");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(r);
int cid = AssertColumn(r, "id");
int cname = AssertColumn(r, "login");
int csuper_user = AssertColumn(r, "super_user");
int cgroup_id = AssertColumn(r, "group_id");
int cemail = AssertColumn(r, "email");
int cnotify = AssertColumn(r, "notify");
int cenv = AssertColumn(r, "env");
int caenv = AssertColumn(r, "aenv");
int cstatus = AssertColumn(r, "status");
int clocale_id = AssertColumn(r, "locale_id");
int ctzone_id = AssertColumn(r, "time_zone_id");
User u;
long last_id = -1;
UGContainer<User>::Iterator iter = user_tab.End();
for(int i=0 ; i<rows ; ++i)
{
u.id = AssertValueLong(r, i, cid);
if( u.id != last_id )
{
u.name = AssertValueWide(r, i, cname);
u.super_user = AssertValueBool(r, i, csuper_user);
u.email = AssertValueWide(r, i, cemail);
u.notify = AssertValueInt(r, i, cnotify);
u.status = AssertValueInt(r, i, cstatus);
u.locale_id = (size_t)AssertValueInt(r, i, clocale_id);
u.time_zone_id = (size_t)AssertValueInt(r, i, ctzone_id);
AssertValueSpace(r, i, cenv, u.env);
AssertValueSpace(r, i, caenv, u.aenv);
log << log2 << "Db: user: id: " << u.id << ", name: " << u.name << ", super_user: " << u.super_user << logend;
iter = user_tab.PushBack(u);
if( iter == user_tab.End() )
log << log1 << "Db: can't add a user: " << u.name << logend;
last_id = u.id;
}
long group_id = AssertValueLong(r, i, cgroup_id);
if( !IsNull(r, i, cgroup_id) && group_id!=-1 && iter!=user_tab.End() )
{
iter->groups.push_back(group_id);
log << log3 << "Db: user:" << iter->name << " is a member of group_id: " << group_id << logend;
}
}
}
catch(const Error &)
{
}
ClearResult(r);
}
void Db::GetGroups(UGContainer<Group> & group_tab)
{
PGresult * r = 0;
try
{
query.Clear();
query << R("select id, core.group.group, user_id from core.group left outer join"
" core.group_mem on core.group.id = core.group_mem.group_id order by id asc;");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(r);
int cid = AssertColumn(r, "id");
int cname = AssertColumn(r, "group");
int cuser_id = AssertColumn(r, "user_id");
Group g;
long last_id = -1;
UGContainer<Group>::Iterator iter;
for(int i = 0 ; i<rows ; ++i)
{
g.id = AssertValueLong(r, i, cid);
if( g.id != last_id )
{
g.name = AssertValueWide(r, i, cname);
log << log3 << "Db: get group, id: " << g.id << ", group: " << g.name << logend;
iter = group_tab.PushBack( g );
last_id = g.id;
}
long user_id = AssertValueLong(r, i, cuser_id);
if( !IsNull(r, i, cuser_id) && user_id!=-1 && !group_tab.Empty() )
{
iter->members.push_back(user_id);
log << log3 << "Db: get group member: user_id: " << user_id << logend;
}
}
}
catch(const Error &)
{
}
ClearResult(r);
}
*/
} // namespace Winix