Skip to content

Commit c7406e0

Browse files
committed
feat(auth): expose high-level public auth facade
Add public auth facade helpers for errors, configuration, passwords, and store creation. Introduce managed auth creation helpers to keep public examples on rix.auth.* and avoid exposing rixlib internals.
1 parent dd4d859 commit c7406e0

3 files changed

Lines changed: 510 additions & 5 deletions

File tree

include/rix/auth/AuthModule.hpp

Lines changed: 268 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <rix/auth/Auth.hpp>
2121
#include <rix/auth/AuthConfig.hpp>
22+
#include <rix/auth/AuthError.hpp>
23+
#include <rix/auth/AuthResult.hpp>
2224
#include <rix/auth/ManagedAuth.hpp>
2325
#include <rix/auth/PasswordHasher.hpp>
2426
#include <rix/auth/SessionStore.hpp>
@@ -29,12 +31,86 @@
2931
#include <rix/auth/stores/MemorySessionStore.hpp>
3032
#include <rix/auth/stores/MemoryUserStore.hpp>
3133

34+
#include <memory>
3235
#include <string>
36+
#include <string_view>
3337

3438
#include <vix/db/Database.hpp>
3539

3640
namespace rixlib::auth
3741
{
42+
/**
43+
* @brief Auth error helpers exposed through rix.auth.error.
44+
*
45+
* This module keeps public examples away from low-level namespace helpers.
46+
*/
47+
class AuthErrorModule
48+
{
49+
public:
50+
/**
51+
* @brief Return a success auth error value.
52+
*
53+
* @return AuthError with AuthErrorCode::None.
54+
*/
55+
[[nodiscard]] AuthError none() const;
56+
57+
/**
58+
* @brief Create an auth error value.
59+
*
60+
* @param code Stable auth error code.
61+
* @param message Human-readable error message.
62+
* @return AuthError value.
63+
*/
64+
[[nodiscard]] AuthError make(
65+
AuthErrorCode code,
66+
std::string message) const;
67+
68+
/**
69+
* @brief Convert an auth error code to a stable string.
70+
*
71+
* @param code Auth error code.
72+
* @return Stable string representation.
73+
*/
74+
[[nodiscard]] std::string_view to_string(
75+
AuthErrorCode code) const noexcept;
76+
77+
/**
78+
* @brief Convert an auth error value to a stable string.
79+
*
80+
* @param error Auth error value.
81+
* @return Stable string representation.
82+
*/
83+
[[nodiscard]] std::string_view to_string(
84+
const AuthError &error) const noexcept;
85+
86+
/**
87+
* @brief Return true when the error is success.
88+
*
89+
* @param error Auth error value.
90+
* @return true if the error code is None.
91+
*/
92+
[[nodiscard]] bool ok(const AuthError &error) const noexcept;
93+
94+
/**
95+
* @brief Return true when the error is failure.
96+
*
97+
* @param error Auth error value.
98+
* @return true if the error code is not None.
99+
*/
100+
[[nodiscard]] bool failed(const AuthError &error) const noexcept;
101+
102+
/**
103+
* @brief Return true when the error has the given code.
104+
*
105+
* @param error Auth error value.
106+
* @param code Expected auth error code.
107+
* @return true if the code matches.
108+
*/
109+
[[nodiscard]] bool is(
110+
const AuthError &error,
111+
AuthErrorCode code) const noexcept;
112+
};
113+
38114
/**
39115
* @brief Auth configuration facade exposed through rix.auth.config.
40116
*/
@@ -54,6 +130,43 @@ namespace rixlib::auth
54130
* @return Production AuthConfig.
55131
*/
56132
[[nodiscard]] AuthConfig production() const;
133+
134+
/**
135+
* @brief Return a development config with a custom minimum password length.
136+
*
137+
* @param min_length Minimum accepted password length.
138+
* @return Development AuthConfig.
139+
*/
140+
[[nodiscard]] AuthConfig development_with_min_password_length(
141+
std::size_t min_length) const;
142+
143+
/**
144+
* @brief Return a production config with a custom minimum password length.
145+
*
146+
* @param min_length Minimum accepted password length.
147+
* @return Production AuthConfig.
148+
*/
149+
[[nodiscard]] AuthConfig production_with_min_password_length(
150+
std::size_t min_length) const;
151+
152+
/**
153+
* @brief Return true when the config looks usable.
154+
*
155+
* This is intentionally conservative. It catches obvious configuration
156+
* mistakes before the user creates an auth service.
157+
*
158+
* @param config Auth configuration.
159+
* @return true if the configuration is accepted.
160+
*/
161+
[[nodiscard]] bool valid(const AuthConfig &config) const noexcept;
162+
163+
/**
164+
* @brief Validate an auth configuration.
165+
*
166+
* @param config Auth configuration.
167+
* @return AuthStatus indicating success or the first validation error.
168+
*/
169+
[[nodiscard]] AuthStatus validate(const AuthConfig &config) const;
57170
};
58171

59172
/**
@@ -71,6 +184,18 @@ namespace rixlib::auth
71184
[[nodiscard]] AuthResult<std::string>
72185
hash(std::string_view password) const;
73186

187+
/**
188+
* @brief Hash a plain-text password using the given auth config.
189+
*
190+
* @param password Plain-text password.
191+
* @param config Auth configuration.
192+
* @return Encoded password hash on success.
193+
*/
194+
[[nodiscard]] AuthResult<std::string>
195+
hash(
196+
std::string_view password,
197+
const AuthConfig &config) const;
198+
74199
/**
75200
* @brief Verify a password against an encoded password hash.
76201
*
@@ -82,25 +207,119 @@ namespace rixlib::auth
82207
std::string_view password,
83208
std::string_view password_hash) const;
84209

210+
/**
211+
* @brief Verify a password against an encoded password hash using config.
212+
*
213+
* @param password Plain-text password.
214+
* @param password_hash Encoded password hash.
215+
* @param config Auth configuration.
216+
* @return true when the password matches.
217+
*/
218+
[[nodiscard]] bool verify(
219+
std::string_view password,
220+
std::string_view password_hash,
221+
const AuthConfig &config) const;
222+
223+
/**
224+
* @brief Return true when the password satisfies default policy.
225+
*
226+
* @param password Plain-text password.
227+
* @return true if accepted.
228+
*/
229+
[[nodiscard]] bool accepts(std::string_view password) const;
230+
231+
/**
232+
* @brief Return true when the password satisfies the given config.
233+
*
234+
* @param password Plain-text password.
235+
* @param config Auth configuration.
236+
* @return true if accepted.
237+
*/
238+
[[nodiscard]] bool accepts(
239+
std::string_view password,
240+
const AuthConfig &config) const;
241+
85242
/**
86243
* @brief Return a new password hasher with default settings.
87244
*
88245
* @return PasswordHasher instance.
89246
*/
90247
[[nodiscard]] PasswordHasher hasher() const;
248+
249+
/**
250+
* @brief Return a new password hasher with the given config.
251+
*
252+
* @param config Auth configuration.
253+
* @return PasswordHasher instance.
254+
*/
255+
[[nodiscard]] PasswordHasher hasher(const AuthConfig &config) const;
256+
};
257+
258+
/**
259+
* @brief Store factory helpers exposed through rix.auth.stores.
260+
*
261+
* This allows advanced users to create stores without manually depending on
262+
* concrete store class names in public examples.
263+
*/
264+
class AuthStoreModule
265+
{
266+
public:
267+
/**
268+
* @brief Create a memory user store.
269+
*
270+
* @return Memory user store.
271+
*/
272+
[[nodiscard]] std::unique_ptr<UserStore> memory_users() const;
273+
274+
/**
275+
* @brief Create a memory session store.
276+
*
277+
* @return Memory session store.
278+
*/
279+
[[nodiscard]] std::unique_ptr<SessionStore> memory_sessions() const;
280+
281+
/**
282+
* @brief Create a database user store.
283+
*
284+
* @param database Vix database facade.
285+
* @return Database user store.
286+
*/
287+
[[nodiscard]] std::unique_ptr<UserStore>
288+
database_users(vix::db::Database &database) const;
289+
290+
/**
291+
* @brief Create a database session store.
292+
*
293+
* @param database Vix database facade.
294+
* @return Database session store.
295+
*/
296+
[[nodiscard]] std::unique_ptr<SessionStore>
297+
database_sessions(vix::db::Database &database) const;
91298
};
92299

93300
/**
94301
* @brief High-level authentication facade exposed through rix.auth.
95302
*
96-
* AuthModule is the simple public entry point used by the global Rix facade.
97-
* It can create memory-backed auth services for examples and tests,
98-
* database-backed auth services for durable applications, or Auth services
99-
* from custom stores.
303+
* AuthModule is the public entry point used by the global Rix facade.
304+
*
305+
* Public examples should prefer:
306+
*
307+
* @code
308+
* auto auth = rix.auth.memory();
309+
* auto auth = rix.auth.database(db);
310+
* @endcode
311+
*
312+
* Lower-level caller-owned store APIs are still available for advanced
313+
* integration, but managed APIs are the safer default.
100314
*/
101315
class AuthModule
102316
{
103317
public:
318+
/**
319+
* @brief Error helpers.
320+
*/
321+
AuthErrorModule error{};
322+
104323
/**
105324
* @brief Configuration helpers.
106325
*/
@@ -111,9 +330,19 @@ namespace rixlib::auth
111330
*/
112331
AuthPasswordModule password{};
113332

333+
/**
334+
* @brief Store factory helpers.
335+
*/
336+
AuthStoreModule stores{};
337+
114338
/**
115339
* @brief Create an Auth service with caller-owned stores.
116340
*
341+
* This is an advanced API. The caller must guarantee that both stores
342+
* outlive the returned Auth service.
343+
*
344+
* Prefer memory(), database(), or managed() for public application code.
345+
*
117346
* @param users User storage backend.
118347
* @param sessions Session storage backend.
119348
* @return Auth service using development defaults.
@@ -125,6 +354,11 @@ namespace rixlib::auth
125354
/**
126355
* @brief Create an Auth service with caller-owned stores and config.
127356
*
357+
* This is an advanced API. The caller must guarantee that both stores
358+
* outlive the returned Auth service.
359+
*
360+
* Prefer memory(), database(), or managed() for public application code.
361+
*
128362
* @param users User storage backend.
129363
* @param sessions Session storage backend.
130364
* @param config Authentication configuration.
@@ -135,6 +369,36 @@ namespace rixlib::auth
135369
SessionStore &sessions,
136370
AuthConfig config) const;
137371

372+
/**
373+
* @brief Create a managed auth service from owned stores.
374+
*
375+
* This is the safe custom-store API. The returned ManagedAuth owns the
376+
* stores and prevents dangling references.
377+
*
378+
* @param users Owned user storage backend.
379+
* @param sessions Owned session storage backend.
380+
* @return Managed auth service or configuration/store error.
381+
*/
382+
[[nodiscard]] AuthResult<ManagedAuth> managed(
383+
std::unique_ptr<UserStore> users,
384+
std::unique_ptr<SessionStore> sessions) const;
385+
386+
/**
387+
* @brief Create a managed auth service from owned stores and config.
388+
*
389+
* This is the safe custom-store API. The returned ManagedAuth owns the
390+
* stores and prevents dangling references.
391+
*
392+
* @param users Owned user storage backend.
393+
* @param sessions Owned session storage backend.
394+
* @param config Authentication configuration.
395+
* @return Managed auth service or configuration/store error.
396+
*/
397+
[[nodiscard]] AuthResult<ManagedAuth> managed(
398+
std::unique_ptr<UserStore> users,
399+
std::unique_ptr<SessionStore> sessions,
400+
AuthConfig config) const;
401+
138402
/**
139403
* @brief Create a memory-backed managed Auth service.
140404
*

0 commit comments

Comments
 (0)