1 /*
2  * User.hpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant to the terms of a commercial license agreement
7  * with RStudio, then this program is licensed to you under the following terms:
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
10  * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #ifndef SHARED_CORE_USER_HPP
25 #define SHARED_CORE_USER_HPP
26 
27 #include <string>
28 
29 #ifndef _WIN32
30 #include <unistd.h>
31 #endif
32 
33 #include <shared_core/PImpl.hpp>
34 
35 namespace rstudio {
36 namespace core {
37 
38 class Error;
39 class FilePath;
40 
41 } // namespace core
42 } // namespace rstudio
43 
44 
45 namespace rstudio {
46 namespace core {
47 namespace system {
48 
49 #ifndef _WIN32
50 typedef uid_t  UidType;
51 typedef gid_t  GidType;
52 #else
53 namespace detail {
54 
55 /**
56  * @brief Gets an environment variable with the specified name.
57  *
58  * @param in_name   The name of the environment variable to retrieve.
59  *
60  * @return The value of the environment variable.
61  */
62 std::string getenv(const std::string& name);
63 
64 } // namespace detail
65 
66 #endif
67 
68 /**
69  * @brief Class which represents a system user.
70  */
71 class User
72 {
73 public:
74 
75    /**
76     * @brief Gets the user home path, as set in the environment.
77     *
78     * @param in_envOverride     If set, overrides the name of the environment variable to use as the user's home path.
79     *                           Multiple overrides may be specified by delimiting them with '|' in order of precedence.
80     *
81     * @return The user home path, as set in the environment.
82     */
83    static FilePath getUserHomePath(const std::string& in_envOverride = std::string());
84 
85 #ifndef _WIN32
86 
87    /**
88     * @brief Constructor.
89     *
90     * Creates a user object which is either empty or represents all users.
91     *
92     * @param in_isEmpty    True to create an empty user; False to create a user which represents all users.
93     *                      Default: false.
94     */
95     explicit User(bool in_isEmpty = false);
96 
97    /**
98     * @brief Copy constructor.
99     *
100     * @param in_other   The user to copy.
101     */
102    User(const User& in_other);
103 
104    /**
105     * @brief Move constructor.
106     *
107     * @param in_other   The user to move into this User.
108     */
109    User(User&& in_other) noexcept = default;
110 
111    /**
112     * @brief Gets the current user.
113     *
114     * @param out_currentUser    The user this process is currently executing on behalf of. This object will be the empty
115     *                           user if this function returns an error.
116     *
117     * @return Success if the user could be retrieved; Error otherwise.
118     */
119    static Error getCurrentUser(User& out_currentUser);
120 
121    /**
122     * @brief Gets a user from its username.
123     *
124     * @param in_username    The name of the user to create.
125     * @param out_user       The created user.
126     *
127     * @return Success if the user could be retrieved; Error otherwise.
128     */
129    static Error getUserFromIdentifier(const std::string& in_username, User& out_user);
130 
131    /**
132     * @brief Gets a user from its user ID.
133     *
134     * @param in_userId      The ID of the user to create.
135     * @param out_user       The created user.
136     *
137     * @return Success if the user could be retrieved; Error otherwise.
138     */
139    static Error getUserFromIdentifier(UidType in_userId, User& out_user);
140 
141    /**
142     * @brief Overloaded assignment operator.
143     *
144     * @param in_other   The user to copy to this one.
145     *
146     * @return This user.
147     */
148    User& operator=(const User& in_other);
149 
150    /**
151     * @brief Overloaded move operator.
152     *
153     * @param in_other   The user to move to this one.
154     *
155     * @return This user.
156     */
157    User& operator=(User&& in_other) noexcept = default;
158 
159    /**
160     * @brief Equality operator.
161     *
162     * @param in_other      The user to compare with this user.
163     *
164     * @return True if this user and in_other have the same user ID; false otherwise.
165     */
166    bool operator==(const User& in_other) const;
167 
168    /**
169     * @brief Inequality operator.
170     *
171     * @param in_other      The user to compare with this user.
172     *
173     * @return False if this user and in_other have the same user ID; true otherwise.
174     */
175    bool operator!=(const User& in_other) const;
176 
177    /**
178     * @brief Checks whether the user represented by this object exists.
179     *
180     * If this is an empty user, or is a user object which represents all users, this method will return false as it does
181     * not represent a user which exists on the system.
182     *
183     * @return True if this user exists; false otherwise.
184     */
185    bool exists() const;
186 
187    /**
188     * @brief Returns whether this object represents all users or not. See the default constructor for more details.
189     *
190     * @return True if this object represents all users; false otherwise.
191     */
192    bool isAllUsers() const;
193 
194    /**
195     * @brief Checks whether this user is empty or not.
196     *
197     * @return True if this is user is empty; False otherwise.
198     */
199    bool isEmpty() const;
200 
201    /**
202     * @brief Gets the user home path, if it exists.
203     *
204     * @return The user's home path, if it exists; empty path otherwise.
205     */
206    const FilePath& getHomePath() const;
207 
208    /**
209     * @brief Gets the ID of this user's primary group.
210     *
211     * @return The ID of this user's primary group.
212     */
213    GidType getGroupId() const;
214 
215    /**
216     * @brief Returns the login shell of this user.
217     *
218     * @return The login shell of this user.
219     */
220    const std::string& getShell() const;
221 
222    /**
223     * @brief Gets the ID of this user.
224     *
225     * @return The ID of this user.
226     */
227    UidType getUserId() const;
228 
229    /**
230     * @brief Returns the name of this user.
231     *
232     * @return The name of this user ("*" for all users).
233     */
234    const std::string& getUsername() const;
235 
236 private:
237    // The private implementation of User.
238    PRIVATE_IMPL(m_impl);
239 
240 #else
241    // No construction on windows.
242    User() = delete;
243 
244 #endif
245 };
246 
247 } // namesapce system
248 } // namespace core
249 } // namespace rstudio
250 
251 #endif
252