diff options
author | Attila Molnar <attilamolnar@hush.com> | 2015-11-02 13:28:55 +0100 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2015-11-02 13:28:55 +0100 |
commit | 30fc51c6ddca487a1b89da9ab0ab59da003aee36 (patch) | |
tree | 8727403ddfdc51441db940ba77d2cce6cea3ec66 /include | |
parent | a6b53dbc3629eb329b5b77d81e81ced837d4dc66 (diff) |
Rewrite invite system
- Moved out of core, now lives entirely in core_channel
- Accessible using the provided API after including the appropriate header
- Invites are stored in an extension attached to LocalUser/Channel objects, they no longer need special handling when destroying these objects or when lowering TS
- Expiration of timed invites are implemented using Timers
- When creating a new invite let a non-timed invite override a timed one
Diffstat (limited to 'include')
-rw-r--r-- | include/channels.h | 2 | ||||
-rw-r--r-- | include/membership.h | 83 | ||||
-rw-r--r-- | include/modules/invite.h | 121 | ||||
-rw-r--r-- | include/usermanager.h | 1 | ||||
-rw-r--r-- | include/users.h | 23 |
5 files changed, 123 insertions, 107 deletions
diff --git a/include/channels.h b/include/channels.h index 4d1d14c13..be84ac800 100644 --- a/include/channels.h +++ b/include/channels.h @@ -34,7 +34,7 @@ * This class represents a channel, and contains its name, modes, topic, topic set time, * etc, and an instance of the BanList type. */ -class CoreExport Channel : public Extensible, public InviteBase<Channel> +class CoreExport Channel : public Extensible { public: /** A map of Memberships on a channel keyed by User pointers diff --git a/include/membership.h b/include/membership.h index 11c142912..05d6b3796 100644 --- a/include/membership.h +++ b/include/membership.h @@ -112,86 +112,3 @@ class CoreExport Membership : public Extensible, public insp::intrusive_list_nod */ const char* GetAllPrefixChars() const; }; - -template <typename T> -class InviteBase -{ - protected: - /** List of pending Invitations - */ - insp::intrusive_list<Invitation, T> invites; - - public: - /** Remove and destruct all pending invitations this user or channel has. - * Must be called before the object is destroyed, also called when the TS of the channel is lowered. - */ - void ClearInvites(); - - friend class Invitation; -}; - -/** - * The Invitation class contains all data about a pending invitation. - * Invitation objects are referenced from the user and the channel they belong to. - */ -class CoreExport Invitation : public insp::intrusive_list_node<Invitation, Channel>, public insp::intrusive_list_node<Invitation, LocalUser> -{ - /** Constructs an Invitation, only called by Create() - * @param c Channel the user is invited to - * @param u User being invited - * @param timeout Expiration time for this Invitation - */ - Invitation(Channel* c, LocalUser* u, time_t timeout) : user(u), chan(c), expiry(timeout) {} - - public: - /** User the invitation is for - */ - LocalUser* const user; - - /** Channel where the user is invited to - */ - Channel* const chan; - - /** Timestamp when this Invitation expires or 0 if it doesn't expire. - * Invitation::Create() can update this field; see that for more info. - */ - time_t expiry; - - /** Destructor - * Removes references to this Invitation from the associated user and channel. - */ - ~Invitation(); - - /** Create or extend an Invitation. - * When a user is invited to join a channel either a new Invitation object is created or - * or the expiration timestamp is updated if there is already a pending Invitation for - * the given (user, channel) pair and the new expiration time is further than the current. - * @param c Target channel - * @param u Target user - * @param timeout Timestamp when the invite should expire, 0 for no expiration - */ - static void Create(Channel* c, LocalUser* u, time_t timeout); - - /** Finds the Invitation object for the given channel/user pair. - * @param c Target channel, can be NULL to remove expired entries - * @param u Target user, cannot be NULL - * @param check_expired Pass true to remove all expired invites found while searching, false - * to return with an Invitation even if it's expired - * @return Invitation object for the given (channel, user) pair if it exists, NULL otherwise - */ - static Invitation* Find(Channel* c, LocalUser* u, bool check_expired = true); -}; - -typedef insp::intrusive_list<Invitation, LocalUser> InviteList; - -template<typename T> -inline void InviteBase<T>::ClearInvites() -{ - for (typename insp::intrusive_list<Invitation, T>::iterator i = invites.begin(); i != invites.end(); ) - { - Invitation* inv = *i; - // Destructing the Invitation invalidates the iterator, so move it now - ++i; - delete inv; - } -} diff --git a/include/modules/invite.h b/include/modules/invite.h new file mode 100644 index 000000000..ab907e970 --- /dev/null +++ b/include/modules/invite.h @@ -0,0 +1,121 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2012, 2015 Attila Molnar <attilamolnar@hush.com> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +namespace Invite +{ + class APIBase; + class API; + class Invite; + + typedef insp::intrusive_list<Invite, LocalUser> List; +} + +class Invite::APIBase : public DataProvider +{ + public: + APIBase(Module* parent); + + /** Create or extend an Invite. + * When a user is invited to join a channel either a new Invite object is created or + * or the expiration timestamp is updated if there is already a pending Invite for + * the given (user, channel) pair and the new expiration time is further than the current. + * @param user Target user + * @param chan Target channel + * @param timeout Timestamp when the invite should expire, 0 for no expiration + */ + virtual void Create(LocalUser* user, Channel* chan, time_t timeout) = 0; + + /** Retrieves the Invite object for the given (user, channel) pair + * @param user Target user + * @param chan Target channel + * @return Invite object for the given (channel, user) pair if it exists, NULL otherwise + */ + virtual Invite* Find(LocalUser* user, Channel* chan) = 0; + + /** Returns the list of channels a user has been invited to but has not yet joined. + * @param user User whose invite list to retrieve + * @return List of channels the user is invited to or NULL if the list is empty + */ + virtual const List* GetList(LocalUser* user) = 0; + + /** Check if a user is invited to a channel + * @param user User to check + * @param chan Channel to check + * @return True if the user is invited to the channel, false otherwise + */ + bool IsInvited(LocalUser* user, Channel* chan) { return (Find(user, chan) != NULL); } + + /** Removes an Invite if it exists + * @param user User whose invite to remove + * @param chan Channel to remove the invite to + * @return True if the user was invited to the channel and the invite was removed, false if the user wasn't invited + */ + virtual bool Remove(LocalUser* user, Channel* chan) = 0; +}; + +class Invite::API : public dynamic_reference<APIBase> +{ + public: + API(Module* parent) + : dynamic_reference<APIBase>(parent, "core_channel_invite") + { + } +}; + +/** + * The Invite class contains all data about a pending invite. + * Invite objects are referenced from the user and the channel they belong to. + */ +class Invite::Invite : public insp::intrusive_list_node<Invite, LocalUser>, public insp::intrusive_list_node<Invite, Channel> +{ + public: + /** User the invite is for + */ + LocalUser* const user; + + /** Channel where the user is invited to + */ + Channel* const chan; + + /** Check whether the invite will expire or not + * @return True if the invite is timed, false if it doesn't expire + */ + bool IsTimed() const { return (expiretimer != NULL); } + + friend class APIImpl; + + private: + /** Timer handling expiration. If NULL this invite doesn't expire. + */ + Timer* expiretimer; + + /** Constructor, only available to the module providing the invite API (core_channel). + * To create Invites use InviteAPI::Create(). + * @param user User being invited + * @param chan Channel the user is invited to + */ + Invite(LocalUser* user, Channel* chan); + + /** Destructor, only available to the module providing the invite API (core_channel). + * To remove Invites use InviteAPI::Remove(). + */ + ~Invite(); +}; diff --git a/include/usermanager.h b/include/usermanager.h index a67f90224..eee076802 100644 --- a/include/usermanager.h +++ b/include/usermanager.h @@ -85,7 +85,6 @@ class CoreExport UserManager : public fakederef<UserManager> /** * Reset the already_sent IDs so we don't wrap it around and drop a message - * Also removes all expired invites */ void GarbageCollect(); diff --git a/include/users.h b/include/users.h index fa8f610bc..03540018b 100644 --- a/include/users.h +++ b/include/users.h @@ -641,7 +641,7 @@ class CoreExport UserIOHandler : public StreamSocket typedef unsigned int already_sent_t; -class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public insp::intrusive_list_node<LocalUser> +class CoreExport LocalUser : public User, public insp::intrusive_list_node<LocalUser> { public: LocalUser(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); @@ -748,27 +748,6 @@ class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public i void Write(const std::string& text); void Write(const char*, ...) CUSTOM_PRINTF(2, 3); - /** Returns the list of channels this user has been invited to but has not yet joined. - * @return A list of channels the user is invited to - */ - InviteList& GetInviteList(); - - /** Returns true if a user is invited to a channel. - * @param chan A channel to look up - * @return True if the user is invited to the given channel - */ - bool IsInvited(Channel* chan) { return (Invitation::Find(chan, this) != NULL); } - - /** Removes a channel from a users invite list. - * This member function is called on successfully joining an invite only channel - * to which the user has previously been invited, to clear the invitation. - * @param chan The channel to remove the invite to - * @return True if the user was invited to the channel and the invite was erased, false if the user wasn't invited - */ - bool RemoveInvite(Channel* chan); - - void RemoveExpiredInvites(); - /** Returns true or false for if a user can execute a privilaged oper command. * This is done by looking up their oper type from User::oper, then referencing * this to their oper classes and checking the commands they can execute. |