forked from Telodendria/Telodendria
Implement user login.
This commit is contained in:
parent
bd88c01c26
commit
121682c006
3 changed files with 192 additions and 14 deletions
|
@ -202,11 +202,32 @@ ROUTE_IMPL(RouteRegister, args)
|
||||||
|
|
||||||
user = UserCreate(db, username, password);
|
user = UserCreate(db, username, password);
|
||||||
response = HashMapCreate();
|
response = HashMapCreate();
|
||||||
HashMapSet(response, "user_id", JsonValueString(StrConcat(4, "@", UserGetName(user), ":", args->matrixArgs->config->serverName)));
|
HashMapSet(response, "user_id", JsonValueString(StrConcat(4, "@",
|
||||||
|
UserGetName(user), ":", args->matrixArgs->config->serverName)));
|
||||||
HttpResponseStatus(args->context, HTTP_OK);
|
HttpResponseStatus(args->context, HTTP_OK);
|
||||||
if (!inhibitLogin)
|
if (!inhibitLogin)
|
||||||
{
|
{
|
||||||
/* TODO: Log in user here and attach auth info to response */
|
UserLoginInfo *loginInfo = UserLogin(user, password, deviceId,
|
||||||
|
initialDeviceDisplayName, refreshToken);
|
||||||
|
|
||||||
|
HashMapSet(response, "access_token",
|
||||||
|
JsonValueString(loginInfo->accessToken));
|
||||||
|
HashMapSet(response, "device_id",
|
||||||
|
JsonValueString(loginInfo->deviceId));
|
||||||
|
|
||||||
|
if (refreshToken)
|
||||||
|
{
|
||||||
|
HashMapSet(response, "expires_in_ms",
|
||||||
|
JsonValueInteger(loginInfo->tokenLifetime));
|
||||||
|
HashMapSet(response, "refresh_token",
|
||||||
|
JsonValueString(loginInfo->refreshToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't need to free members; they're attached to the JSON response,
|
||||||
|
* they will be freed after the response is sent.
|
||||||
|
*/
|
||||||
|
Free(loginInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(lc, LOG_INFO, "Registered user '%s'", UserGetName(user));
|
Log(lc, LOG_INFO, "Registered user '%s'", UserGetName(user));
|
||||||
|
|
165
src/User.c
165
src/User.c
|
@ -186,22 +186,128 @@ UserCreate(Db * db, char *name, char *password)
|
||||||
hash = Sha256(tmpstr);
|
hash = Sha256(tmpstr);
|
||||||
Free(tmpstr);
|
Free(tmpstr);
|
||||||
HashMapSet(json, "salt", JsonValueString(salt));
|
HashMapSet(json, "salt", JsonValueString(salt));
|
||||||
HashMapSet(json, "hash", JsonValueString(hash));
|
HashMapSet(json, "password", JsonValueString(hash));
|
||||||
|
|
||||||
HashMapSet(json, "created_on", JsonValueInteger(ts));
|
HashMapSet(json, "createdOn", JsonValueInteger(ts));
|
||||||
HashMapSet(json, "last_updated", JsonValueInteger(ts));
|
HashMapSet(json, "deactivated", JsonValueBoolean(0));
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
UserLoginInfo *
|
||||||
UserLogin(User * user, char *password, char *deviceId, char *deviceDisplayName)
|
UserLogin(User * user, char *password, char *deviceId, char *deviceDisplayName,
|
||||||
|
int withRefresh)
|
||||||
{
|
{
|
||||||
/* TODO: Implement login */
|
DbRef *atRef;
|
||||||
(void) user;
|
DbRef *rtRef = NULL;
|
||||||
(void) password;
|
|
||||||
(void) deviceId;
|
HashMap *devices;
|
||||||
(void) deviceDisplayName;
|
HashMap *device;
|
||||||
|
|
||||||
|
UserLoginInfo *result;
|
||||||
|
|
||||||
|
if (!user || !password)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UserCheckPassword(user, password))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Malloc(sizeof(UserLoginInfo));
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->refreshToken = NULL;
|
||||||
|
result->tokenLifetime = 0;
|
||||||
|
|
||||||
|
/* Generate an access token */
|
||||||
|
result->accessToken = StrRandom(64);
|
||||||
|
atRef = DbCreate(user->db, 3, "tokens", "access", result->accessToken);
|
||||||
|
|
||||||
|
HashMapSet(DbJson(atRef), "user", JsonValueString(StrDuplicate(user->name)));
|
||||||
|
|
||||||
|
if (withRefresh)
|
||||||
|
{
|
||||||
|
unsigned long ts = UtilServerTs();
|
||||||
|
|
||||||
|
result->tokenLifetime = 1000 * 60 * 60 * 24 * 7; /* 1 Week */
|
||||||
|
|
||||||
|
result->refreshToken = StrRandom(64);
|
||||||
|
rtRef = DbCreate(user->db, 3, "tokens", "refresh", result->refreshToken);
|
||||||
|
|
||||||
|
HashMapSet(DbJson(rtRef), "refreshes",
|
||||||
|
JsonValueString(StrDuplicate(result->accessToken)));
|
||||||
|
HashMapSet(DbJson(atRef), "expires", JsonValueInteger(ts + result->tokenLifetime));
|
||||||
|
DbUnlock(user->db, rtRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deviceId)
|
||||||
|
{
|
||||||
|
result->deviceId = StrRandom(10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result->deviceId = StrDuplicate(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
devices = JsonValueAsObject(HashMapGet(DbJson(user->ref), "devices"));
|
||||||
|
if (!devices)
|
||||||
|
{
|
||||||
|
devices = HashMapCreate();
|
||||||
|
HashMapSet(DbJson(user->ref), "devices", JsonValueObject(devices));
|
||||||
|
}
|
||||||
|
|
||||||
|
device = JsonValueAsObject(HashMapGet(devices, result->deviceId));
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
{
|
||||||
|
JsonValue *val;
|
||||||
|
|
||||||
|
val = HashMapDelete(device, "accessToken");
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
DbDelete(user->db, 3, "tokens", "access", JsonValueAsString(val));
|
||||||
|
JsonValueFree(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = HashMapDelete(device, "refreshToken");
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
DbDelete(user->db, 3, "tokens", "refresh", JsonValueAsString(val));
|
||||||
|
JsonValueFree(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
device = HashMapCreate();
|
||||||
|
HashMapSet(devices, StrDuplicate(result->deviceId), JsonValueObject(device));
|
||||||
|
|
||||||
|
if (deviceDisplayName)
|
||||||
|
{
|
||||||
|
HashMapSet(device, "displayName",
|
||||||
|
JsonValueString(StrDuplicate(deviceDisplayName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->refreshToken)
|
||||||
|
{
|
||||||
|
HashMapSet(device, "refreshToken",
|
||||||
|
JsonValueString(StrDuplicate(result->refreshToken)));
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMapSet(device, "accessToken",
|
||||||
|
JsonValueString(StrDuplicate(result->accessToken)));
|
||||||
|
|
||||||
|
HashMapSet(DbJson(atRef), "device", JsonValueString(StrDuplicate(result->deviceId)));
|
||||||
|
DbUnlock(user->db, atRef);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -209,3 +315,42 @@ UserGetName(User * user)
|
||||||
{
|
{
|
||||||
return user ? user->name : NULL;
|
return user ? user->name : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
UserCheckPassword(User * user, char *password)
|
||||||
|
{
|
||||||
|
HashMap *json;
|
||||||
|
|
||||||
|
char *storedHash;
|
||||||
|
char *salt;
|
||||||
|
|
||||||
|
char *hashedPwd;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!user || !password)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json = DbJson(user->ref);
|
||||||
|
|
||||||
|
storedHash = JsonValueAsString(HashMapGet(json, "password"));
|
||||||
|
salt = JsonValueAsString(HashMapGet(json, "salt"));
|
||||||
|
|
||||||
|
if (!storedHash || !salt)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = StrConcat(2, password, salt);
|
||||||
|
hashedPwd = Sha256(tmp);
|
||||||
|
Free(tmp);
|
||||||
|
|
||||||
|
result = strcmp(hashedPwd, storedHash) == 0;
|
||||||
|
|
||||||
|
Free(hashedPwd);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,14 @@
|
||||||
|
|
||||||
typedef struct User User;
|
typedef struct User User;
|
||||||
|
|
||||||
|
typedef struct UserLoginInfo
|
||||||
|
{
|
||||||
|
char *accessToken;
|
||||||
|
char *refreshToken;
|
||||||
|
char *deviceId;
|
||||||
|
long tokenLifetime;
|
||||||
|
} UserLoginInfo;
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
UserValidate(char *, char *);
|
UserValidate(char *, char *);
|
||||||
|
|
||||||
|
@ -46,10 +54,14 @@ extern User *
|
||||||
extern int
|
extern int
|
||||||
UserUnlock(User *);
|
UserUnlock(User *);
|
||||||
|
|
||||||
extern void
|
extern UserLoginInfo *
|
||||||
UserLogin(User *, char *password, char *deviceId, char *deviceDisplayName);
|
UserLogin(User *, char *password, char *deviceId, char *deviceDisplayName,
|
||||||
|
int withRefresh);
|
||||||
|
|
||||||
extern char *
|
extern char *
|
||||||
UserGetName(User *);
|
UserGetName(User *);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
UserCheckPassword(User *, char *);
|
||||||
|
|
||||||
#endif /* TELODENDRIA_USER_H */
|
#endif /* TELODENDRIA_USER_H */
|
||||||
|
|
Loading…
Reference in a new issue