sharp-chat/SharpChat.Protocol.SockChat/PacketHandlers/AuthPacketHandler.cs

122 lines
5.8 KiB
C#

using SharpChat.Bans;
using SharpChat.Channels;
using SharpChat.Messages;
using SharpChat.Protocol.SockChat.Packets;
using SharpChat.Sessions;
using SharpChat.Users;
using SharpChat.Users.Remote;
using System;
using System.Linq;
namespace SharpChat.Protocol.SockChat.PacketHandlers {
public class AuthPacketHandler : IPacketHandler {
public ClientPacketId PacketId => ClientPacketId.Authenticate;
private SockChatServer Server { get; }
private SessionManager Sessions { get; }
private UserManager Users { get; }
private ChannelManager Channels { get; }
private ChannelUserRelations ChannelUsers { get; }
private MessageManager Messages { get; }
private IRemoteUserClient RemoteUserClient { get; }
private BanManager Bans { get; }
private IUser Sender { get; }
private WelcomeMessage WelcomeMessage { get; }
public AuthPacketHandler(
SockChatServer server,
SessionManager sessions,
UserManager users,
ChannelManager channels,
ChannelUserRelations channelUsers,
MessageManager messages,
IRemoteUserClient remoteUserClient,
BanManager bans,
IUser sender,
WelcomeMessage welcomeMessage
) {
Server = server ?? throw new ArgumentNullException(nameof(server));
Sessions = sessions ?? throw new ArgumentNullException(nameof(sessions));
Users = users ?? throw new ArgumentNullException(nameof(users));
Channels = channels ?? throw new ArgumentNullException(nameof(channels));
ChannelUsers = channelUsers ?? throw new ArgumentNullException(nameof(channelUsers));
Messages = messages ?? throw new ArgumentNullException(nameof(messages));
RemoteUserClient = remoteUserClient ?? throw new ArgumentNullException(nameof(remoteUserClient));
Bans = bans ?? throw new ArgumentNullException(nameof(bans));
Sender = sender ?? throw new ArgumentNullException(nameof(sender));
WelcomeMessage = welcomeMessage ?? throw new ArgumentNullException(nameof(welcomeMessage));
}
public void HandlePacket(PacketHandlerContext ctx) {
if(ctx.HasSession)
return;
if(!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || userId < 1)
return;
string token = ctx.Args.ElementAtOrDefault(2);
if(string.IsNullOrEmpty(token))
return;
Action<Exception> exceptionHandler = new(ex => {
Logger.Debug($@"[{ctx.Connection}] Auth fail: {ex.Message}");
ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.AuthInvalid));
ctx.Connection.Close();
});
RemoteUserClient.AuthenticateUser(
new UserAuthRequest(userId, token, ctx.Connection.RemoteAddress),
res => {
Bans.CheckBan(res, ctx.Connection.RemoteAddress, ban => {
if(ban.IsPermanent || ban.Expires > DateTimeOffset.Now) {
ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.Banned, ban));
ctx.Connection.Close();
return;
}
Users.Connect(res, user => {
Sessions.HasAvailableSessions(user, available => {
if(!available) {
ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.MaxSessions));
ctx.Connection.Close();
return;
}
Sessions.Create(ctx.Connection, user, session => {
// TODO: !!!!!!!!!!!!!!!!
ctx.Connection.Session = session;
session.Connection = ctx.Connection;
string welcome = Server.WelcomeMessage;
if(!string.IsNullOrWhiteSpace(welcome))
ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, welcome.Replace(@"{username}", user.UserName)));
if(WelcomeMessage.HasRandom) {
string line = WelcomeMessage.GetRandomString();
if(!string.IsNullOrWhiteSpace(line))
ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, line));
}
Channels.GetDefaultChannels(channels => {
if(!channels.Any())
return; // what do, this is impossible
// other channels should be joined if MCHAN has been received
IChannel firstChan = channels.FirstOrDefault();
ctx.Connection.LastChannel = firstChan;
ctx.Connection.SendPacket(new AuthSuccessPacket(user, firstChan, session, Messages.TextMaxLength));
Channels.GetChannels(user.Rank, c => ctx.Connection.SendPacket(new ContextChannelsPacket(c)));
ChannelUsers.JoinChannel(firstChan, session);
});
});
});
});
}, exceptionHandler);
},
exceptionHandler
);
}
}
}