mirror of
https://github.com/matrix-construct/construct
synced 2024-09-03 23:35:19 +02:00
334 lines
5.7 KiB
C++
334 lines
5.7 KiB
C++
// Matrix Construct
|
|
//
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
namespace ircd::m
|
|
{
|
|
static string_view gen_password_hash(const mutable_buffer &, const string_view &);
|
|
static room create_user_room(const user::id &, const room::id &, const json::members &contents);
|
|
}
|
|
|
|
bool
|
|
ircd::m::exists(const user::id &user_id)
|
|
{
|
|
// The way we know a user exists is testing if their room exists.
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
return m::exists(user_room);
|
|
}
|
|
|
|
bool
|
|
ircd::m::exists(const user &user)
|
|
{
|
|
return exists(user.user_id);
|
|
}
|
|
|
|
bool
|
|
ircd::m::my(const user &user)
|
|
{
|
|
return my(user.user_id);
|
|
}
|
|
|
|
ircd::m::user
|
|
IRCD_MODULE_EXPORT
|
|
ircd::m::create(const m::user::id &user_id,
|
|
const json::members &contents)
|
|
{
|
|
const m::user user
|
|
{
|
|
user_id
|
|
};
|
|
|
|
const m::room::id::buf room_id
|
|
{
|
|
user.room_id()
|
|
};
|
|
|
|
const m::room room
|
|
{
|
|
create_user_room(user_id, room_id, contents)
|
|
};
|
|
|
|
return user;
|
|
}
|
|
|
|
ircd::m::room
|
|
ircd::m::create_user_room(const user::id &user_id,
|
|
const room::id &room_id,
|
|
const json::members &contents)
|
|
try
|
|
{
|
|
return create(room_id, me(), "user");
|
|
}
|
|
catch(const std::exception &e)
|
|
{
|
|
if(m::exists(room_id))
|
|
return room_id;
|
|
|
|
log::error
|
|
{
|
|
log, "Failed to create user %s room %s :%s",
|
|
string_view{user_id},
|
|
string_view{room_id},
|
|
e.what()
|
|
};
|
|
|
|
throw;
|
|
}
|
|
|
|
//
|
|
// user::user
|
|
//
|
|
|
|
/// Generates a user-room ID into buffer; see room_id() overload.
|
|
ircd::m::id::room::buf
|
|
ircd::m::user::room_id()
|
|
const
|
|
{
|
|
ircd::m::id::room::buf buf;
|
|
return buf.assigned(room_id(buf));
|
|
}
|
|
|
|
/// This generates a room mxid for the "user's room" essentially serving as
|
|
/// a database mechanism for this specific user. This room_id is a hash of
|
|
/// the user's full mxid.
|
|
///
|
|
ircd::m::id::room
|
|
ircd::m::user::room_id(const mutable_buffer &buf)
|
|
const
|
|
{
|
|
assert(!empty(user_id));
|
|
const ripemd160::buf hash
|
|
{
|
|
ripemd160{user_id}
|
|
};
|
|
|
|
char b58[size(hash) * 2];
|
|
return
|
|
{
|
|
buf, b58encode(b58, hash), origin(my())
|
|
};
|
|
}
|
|
|
|
ircd::m::device::id::buf
|
|
ircd::m::user::get_device_from_access_token(const string_view &token)
|
|
{
|
|
const m::room::id::buf tokens_room_id
|
|
{
|
|
"tokens", origin(my())
|
|
};
|
|
|
|
const m::room tokens
|
|
{
|
|
tokens_room_id
|
|
};
|
|
|
|
const event::idx event_idx
|
|
{
|
|
tokens.get("ircd.access_token", token)
|
|
};
|
|
|
|
device::id::buf ret;
|
|
m::get(event_idx, "content", [&ret]
|
|
(const json::object &content)
|
|
{
|
|
ret = unquote(content.at("device_id"));
|
|
});
|
|
|
|
return ret;
|
|
}
|
|
|
|
ircd::string_view
|
|
ircd::m::user::gen_access_token(const mutable_buffer &buf)
|
|
{
|
|
static const size_t token_max{32};
|
|
static const auto &token_dict
|
|
{
|
|
rand::dict::alpha
|
|
};
|
|
|
|
const mutable_buffer out
|
|
{
|
|
data(buf), std::min(token_max, size(buf))
|
|
};
|
|
|
|
return rand::string(token_dict, out);
|
|
}
|
|
|
|
ircd::m::event::id::buf
|
|
ircd::m::user::activate()
|
|
{
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
return send(user_room, m::me(), "ircd.account", "active", json::members
|
|
{
|
|
{ "value", true }
|
|
});
|
|
}
|
|
|
|
ircd::m::event::id::buf
|
|
ircd::m::user::deactivate()
|
|
{
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
return send(user_room, m::me(), "ircd.account", "active", json::members
|
|
{
|
|
{ "value", false }
|
|
});
|
|
}
|
|
|
|
bool
|
|
ircd::m::user::is_active()
|
|
const
|
|
{
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
const m::event::idx &event_idx
|
|
{
|
|
user_room.get(std::nothrow, "ircd.account", "active")
|
|
};
|
|
|
|
return m::query(event_idx, "content", []
|
|
(const json::object &content)
|
|
{
|
|
return content.get<bool>("value", false);
|
|
});
|
|
}
|
|
|
|
ircd::m::event::id::buf
|
|
IRCD_MODULE_EXPORT
|
|
ircd::m::user::password(const string_view &password)
|
|
{
|
|
char buf[64];
|
|
const auto supplied
|
|
{
|
|
gen_password_hash(buf, password)
|
|
};
|
|
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
return send(user_room, user_id, "ircd.password", user_id,
|
|
{
|
|
{ "sha256", supplied }
|
|
});
|
|
}
|
|
|
|
bool
|
|
IRCD_MODULE_EXPORT
|
|
ircd::m::user::is_password(const string_view &password)
|
|
const try
|
|
{
|
|
char buf[64];
|
|
const auto supplied
|
|
{
|
|
gen_password_hash(buf, password)
|
|
};
|
|
|
|
bool ret{false};
|
|
const m::user::room user_room
|
|
{
|
|
user_id
|
|
};
|
|
|
|
const ctx::uninterruptible::nothrow ui;
|
|
user_room.get("ircd.password", user_id, [&supplied, &ret]
|
|
(const m::event &event)
|
|
{
|
|
const json::object &content
|
|
{
|
|
json::at<"content"_>(event)
|
|
};
|
|
|
|
const auto &correct
|
|
{
|
|
unquote(content.at("sha256"))
|
|
};
|
|
|
|
ret = supplied == correct;
|
|
});
|
|
|
|
return ret;
|
|
}
|
|
catch(const m::NOT_FOUND &e)
|
|
{
|
|
return false;
|
|
}
|
|
catch(const std::exception &e)
|
|
{
|
|
log::critical
|
|
{
|
|
"is_password__user(): %s %s",
|
|
string_view{user_id},
|
|
e.what()
|
|
};
|
|
|
|
return false;
|
|
}
|
|
|
|
ircd::string_view
|
|
ircd::m::gen_password_hash(const mutable_buffer &out,
|
|
const string_view &supplied_password)
|
|
{
|
|
//TODO: ADD SALT
|
|
const sha256::buf hash
|
|
{
|
|
sha256{supplied_password}
|
|
};
|
|
|
|
return b64encode_unpadded(out, hash);
|
|
}
|
|
|
|
//
|
|
// user::room
|
|
//
|
|
|
|
ircd::m::user::room::room(const m::user::id &user_id,
|
|
const vm::copts *const &copts,
|
|
const event::fetch::opts *const &fopts)
|
|
:room
|
|
{
|
|
m::user{user_id}, copts, fopts
|
|
}
|
|
{
|
|
}
|
|
|
|
ircd::m::user::room::room(const m::user &user,
|
|
const vm::copts *const &copts,
|
|
const event::fetch::opts *const &fopts)
|
|
:user{user}
|
|
,room_id{user.room_id()}
|
|
{
|
|
static_cast<m::room &>(*this) =
|
|
{
|
|
room_id, copts, fopts
|
|
};
|
|
}
|
|
|
|
bool
|
|
ircd::m::user::room::is(const room::id &room_id,
|
|
const user::id &user_id)
|
|
{
|
|
const user::room user_room{user_id};
|
|
return user_room.room_id == room_id;
|
|
}
|