aboutsummaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/modules/internalsecret.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/modules/internalsecret.c')
-rw-r--r--examples/redis-unstable/tests/modules/internalsecret.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/examples/redis-unstable/tests/modules/internalsecret.c b/examples/redis-unstable/tests/modules/internalsecret.c
new file mode 100644
index 0000000..043089c
--- /dev/null
+++ b/examples/redis-unstable/tests/modules/internalsecret.c
@@ -0,0 +1,154 @@
1#include "redismodule.h"
2#include <errno.h>
3
4int InternalAuth_GetInternalSecret(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
5 REDISMODULE_NOT_USED(argv);
6 REDISMODULE_NOT_USED(argc);
7
8 /* NOTE: The internal secret SHOULD NOT be exposed by any module. This is
9 done for testing purposes only. */
10 size_t len;
11 const char *secret = RedisModule_GetInternalSecret(ctx, &len);
12 if(secret) {
13 RedisModule_ReplyWithStringBuffer(ctx, secret, len);
14 } else {
15 RedisModule_ReplyWithError(ctx, "ERR no internal secret available");
16 }
17 return REDISMODULE_OK;
18}
19
20int InternalAuth_InternalCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
21 REDISMODULE_NOT_USED(argv);
22 REDISMODULE_NOT_USED(argc);
23
24 RedisModule_ReplyWithSimpleString(ctx, "OK");
25 return REDISMODULE_OK;
26}
27
28typedef enum {
29 RM_CALL_REGULAR = 0,
30 RM_CALL_WITHUSER = 1,
31 RM_CALL_WITHDETACHEDCLIENT = 2,
32 RM_CALL_REPLICATED = 3
33} RMCallMode;
34
35int call_rm_call(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, RMCallMode mode) {
36 if(argc < 2){
37 return RedisModule_WrongArity(ctx);
38 }
39 RedisModuleCallReply *rep = NULL;
40 RedisModuleCtx *detached_ctx = NULL;
41 const char* cmd = RedisModule_StringPtrLen(argv[1], NULL);
42
43 switch (mode) {
44 case RM_CALL_REGULAR:
45 // Regular call, with the unrestricted user.
46 rep = RedisModule_Call(ctx, cmd, "vE", argv + 2, (size_t)argc - 2);
47 break;
48 case RM_CALL_WITHUSER:
49 // Simply call the command with the current client.
50 rep = RedisModule_Call(ctx, cmd, "vCE", argv + 2, (size_t)argc - 2);
51 break;
52 case RM_CALL_WITHDETACHEDCLIENT:
53 // Use a context created with the thread-safe-context API
54 detached_ctx = RedisModule_GetThreadSafeContext(NULL);
55 if(!detached_ctx){
56 RedisModule_ReplyWithError(ctx, "ERR failed to create detached context");
57 return REDISMODULE_ERR;
58 }
59 // Dispatch the command with the detached context
60 rep = RedisModule_Call(detached_ctx, cmd, "vCE", argv + 2, (size_t)argc - 2);
61 break;
62 case RM_CALL_REPLICATED:
63 rep = RedisModule_Call(ctx, cmd, "vE", argv + 2, (size_t)argc - 2);
64 }
65
66 if(!rep) {
67 char err[100];
68 switch (errno) {
69 case EACCES:
70 RedisModule_ReplyWithError(ctx, "ERR NOPERM");
71 break;
72 case ENOENT:
73 RedisModule_ReplyWithError(ctx, "ERR unknown command");
74 break;
75 default:
76 snprintf(err, sizeof(err) - 1, "ERR errno=%d", errno);
77 RedisModule_ReplyWithError(ctx, err);
78 break;
79 }
80 } else {
81 RedisModule_ReplyWithCallReply(ctx, rep);
82 RedisModule_FreeCallReply(rep);
83 if (mode == RM_CALL_REPLICATED)
84 RedisModule_ReplicateVerbatim(ctx);
85 }
86
87 if (mode == RM_CALL_WITHDETACHEDCLIENT) {
88 RedisModule_FreeThreadSafeContext(detached_ctx);
89 }
90
91 return REDISMODULE_OK;
92}
93
94int internal_rmcall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
95 return call_rm_call(ctx, argv, argc, RM_CALL_REGULAR);
96}
97
98int noninternal_rmcall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
99 return call_rm_call(ctx, argv, argc, RM_CALL_REGULAR);
100}
101
102int noninternal_rmcall_withuser(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
103 return call_rm_call(ctx, argv, argc, RM_CALL_WITHUSER);
104}
105
106int noninternal_rmcall_detachedcontext_withuser(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
107 return call_rm_call(ctx, argv, argc, RM_CALL_WITHDETACHEDCLIENT);
108}
109
110int internal_rmcall_replicated(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
111 return call_rm_call(ctx, argv, argc, RM_CALL_REPLICATED);
112}
113
114/* This function must be present on each Redis module. It is used in order to
115 * register the commands into the Redis server. */
116int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
117 REDISMODULE_NOT_USED(argv);
118 REDISMODULE_NOT_USED(argc);
119
120 if (RedisModule_Init(ctx,"testinternalsecret",1,REDISMODULE_APIVER_1)
121 == REDISMODULE_ERR) return REDISMODULE_ERR;
122
123 /* WARNING: A module should NEVER expose the internal secret - this is for
124 * testing purposes only. */
125 if (RedisModule_CreateCommand(ctx,"internalauth.getinternalsecret",
126 InternalAuth_GetInternalSecret,"",0,0,0) == REDISMODULE_ERR)
127 return REDISMODULE_ERR;
128
129 if (RedisModule_CreateCommand(ctx,"internalauth.internalcommand",
130 InternalAuth_InternalCommand,"internal",0,0,0) == REDISMODULE_ERR)
131 return REDISMODULE_ERR;
132
133 if (RedisModule_CreateCommand(ctx,"internalauth.internal_rmcall",
134 internal_rmcall,"write internal",0,0,0) == REDISMODULE_ERR)
135 return REDISMODULE_ERR;
136
137 if (RedisModule_CreateCommand(ctx,"internalauth.noninternal_rmcall",
138 noninternal_rmcall,"write",0,0,0) == REDISMODULE_ERR)
139 return REDISMODULE_ERR;
140
141 if (RedisModule_CreateCommand(ctx,"internalauth.noninternal_rmcall_withuser",
142 noninternal_rmcall_withuser,"write",0,0,0) == REDISMODULE_ERR)
143 return REDISMODULE_ERR;
144
145 if (RedisModule_CreateCommand(ctx,"internalauth.noninternal_rmcall_detachedcontext_withuser",
146 noninternal_rmcall_detachedcontext_withuser,"write",0,0,0) == REDISMODULE_ERR)
147 return REDISMODULE_ERR;
148
149 if (RedisModule_CreateCommand(ctx,"internalauth.internal_rmcall_replicated",
150 internal_rmcall_replicated,"write internal",0,0,0) == REDISMODULE_ERR)
151 return REDISMODULE_ERR;
152
153 return REDISMODULE_OK;
154}