/*
TShock, a server mod for Terraria
Copyright (C) 2011 The TShock Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Community.CsharpSqlite.SQLiteClient;
namespace TShockAPI.DB
{
public class UserManager
{
private IDbConnection database;
public UserManager(IDbConnection db)
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'Users' ('ID' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, 'Username' VARCHAR(32) UNIQUE, 'Password' VARCHAR(64), 'Usergroup' TEXT, 'IP' VARCHAR(32));";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS Users (ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, Username VARCHAR(32) UNIQUE, Password VARCHAR(64), Usergroup VARCHAR(255), IP VARCHAR(15));";
com.ExecuteNonQuery();
String file = Path.Combine(TShock.SavePath, "users.txt");
if (File.Exists(file))
{
using (StreamReader sr = new StreamReader(file))
{
String line;
while ((line = sr.ReadLine()) != null )
{
if (line.Equals("") || line.Substring(0, 1).Equals("#") )
continue;
String[] info = line.Split(' ');
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO Users (Username, Password, Usergroup, IP) VALUES (@name, @pass, @group, @ip);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO Bans SET Username=@name, Password=@pass, Usergroup=@group, IP=@ip ;";
String username = "";
String sha = "";
String group = "";
String ip = "";
String[] nameSha = info[0].Split(':');
if (nameSha.Length < 2)
{
username = nameSha[0];
ip = nameSha[0];
group = info[1];
}
else
{
username = nameSha[0];
sha = nameSha[1];
group = info[1];
}
com.AddParameter("@name", username.Trim());
com.AddParameter("@pass", sha.Trim());
com.AddParameter("@group", group.Trim());
com.AddParameter("@ip", ip.Trim());
com.ExecuteNonQuery();
com.Parameters.Clear();
}
}
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "users.txt");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
File.Move(file, file2);
}
}
}
public void AddUser(User user)
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@name, @password, @group, @ip);";
com.AddParameter("@name", user.Name);
com.AddParameter("@password", Tools.HashPassword(user.Password));
if (!TShock.Groups.GroupExists(user.Group))
throw new GroupNotExistsException(user.Group);
com.AddParameter("@group", user.Group);
com.AddParameter("@ip", user.Address);
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
throw new UserExistsException(user.Name);
}
}
}
catch (Exception ex)
{
throw new UserManagerException("AddUser SQL returned an error", ex);
}
}
public void RemoveUser(User user)
{
try
{
using (var com = database.CreateCommand())
{
if (!string.IsNullOrEmpty(user.Address))
{
com.CommandText = "DELETE FROM Users WHERE IP=@ip";
com.AddParameter("@ip", user.Address);
}
else
{
com.CommandText = "DELETE FROM Users WHERE Username=@name";
com.AddParameter("@name", user.Name);
}
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
}
}
}
catch (Exception ex)
{
throw new UserManagerException("RemoveUser SQL returned an error", ex);
}
}
///
/// Fetches the hashed password and group for a given username
///
/// string username
/// string[] {password, group}
public string[] FetchHashedPasswordAndGroup(string username)
{
string[] returndata = new string[2];
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Users WHERE Username=@name";
com.AddParameter("@name", username.ToLower());
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
returndata[0] = reader.Get("Password");
returndata[1] = reader.Get("UserGroup");
return returndata;
}
reader.Close();
}
}
}
catch (Exception ex)
{
Log.ConsoleError("FetchHashedPasswordAndGroup SQL returned an error: " + ex.ToString());
}
return returndata;
}
///
/// Returns a Group for a ip from the database
///
/// string ip
public Group GetGroupForIP(string ip)
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Users WHERE IP=@ip";
com.AddParameter("@ip", ip);
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
string group = reader.Get("UserGroup");
return Tools.GetGroup(group);
}
}
}
}
catch (Exception ex)
{
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex.ToString());
}
return Tools.GetGroup("default");
}
public User GetUserByName(string name)
{
try
{
return GetUser(new User { Name = name });
}
catch (UserManagerException)
{
return null;
}
}
public User GetUserByIP(string ip)
{
try
{
return GetUser(new User { Address = ip });
}
catch (UserManagerException)
{
return null;
}
}
public User GetUser(User user)
{
try
{
using (var com = database.CreateCommand())
{
if (string.IsNullOrEmpty(user.Address))
{
com.CommandText = "SELECT * FROM Users WHERE Username=@name";
com.AddParameter("@name", user.Name);
}
else
{
com.CommandText = "SELECT * FROM Users WHERE IP=@ip";
com.AddParameter("@ip", user.Address);
}
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
user.ID = reader.Get("ID");
user.Group = reader.Get("Usergroup");
return user;
}
}
}
}
catch (Exception ex)
{
throw new UserManagerException("GetUserID SQL returned an error", ex);
}
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
}
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public string Group { get; set; }
public string Address { get; set; }
public User(string ip, string name, string pass, string group)
{
Address = ip;
Name = name;
Password = pass;
Group = group;
}
public User()
{
Address = "";
Name = "";
Password = "";
Group = "";
}
}
public class UserManagerException : Exception
{
public UserManagerException(string message)
: base(message)
{
}
public UserManagerException(string message, Exception inner)
: base(message, inner)
{
}
}
public class UserExistsException : UserManagerException
{
public UserExistsException(string name)
: base("User '" + name + "' already exists")
{
}
}
public class UserNotExistException : UserManagerException
{
public UserNotExistException(string name)
: base("User '" + name + "' does not exist")
{
}
}
public class GroupNotExistsException : UserManagerException
{
public GroupNotExistsException(string group)
: base("Group '" + group + "' does not exist")
{
}
}
}