mirror of
https://github.com/kevachat/webapp.git
synced 2025-01-22 12:34:25 +00:00
implement users registration
This commit is contained in:
parent
a69e6de5e5
commit
c6fef9bb4b
12
.env
12
.env
@ -58,12 +58,24 @@ APP_KEVACOIN_ROOM_NAMESPACES_READONLY=
|
||||
# Redirect from index page to default room
|
||||
APP_KEVACOIN_ROOM_NAMESPACE_DEFAULT=EDIT_ME
|
||||
|
||||
# Session expire
|
||||
APP_SESSION_DEFAULT_TIMEOUT=2592000
|
||||
|
||||
# Online session expiration timeout
|
||||
APP_SESSION_ONLINE_TIMEOUT=900
|
||||
|
||||
# Moderators IP with extra permissions, separated with |
|
||||
APP_MODERATOR_REMOTE_IP=
|
||||
|
||||
# User name regex condition
|
||||
APP_ADD_USER_NAME_REGEX=/^[0-9A-z-]{2,16}$/ui
|
||||
|
||||
# User name reserved (case insensitive) separated with |
|
||||
APP_ADD_USER_NAME_BLACKLIST=KevaChat|admin|moderator|test
|
||||
|
||||
# Delay before have ability to create new username again
|
||||
APP_ADD_USER_REMOTE_IP_DELAY=86400
|
||||
|
||||
# Allow remotes to create new rooms (namespaces)
|
||||
APP_ADD_ROOM_REMOTE_IP_REGEX=/.*/
|
||||
|
||||
|
@ -47,6 +47,7 @@ Application package contain settings preset, just few steps required to launch:
|
||||
* Copy `rpcuser` to `env`.`APP_KEVACOIN_USERNAME` and `rpcpassword` to `env`.`APP_KEVACOIN_PASSWORD`
|
||||
* Generate new address using CLI `kevacoin-cli getnewaddress` and copy to `env`.`APP_KEVACOIN_BOOST_ADDRESS`
|
||||
* Send few coins to this address and wait for new block to continue
|
||||
* To allow users registration, create namespace `kevacoin-cli keva_namespace "_KEVACHAT_USERS_"`
|
||||
* Create at least one room namespace with Web UI or CLI `kevacoin-cli keva_namespace "sandbox"`
|
||||
* Provide at least one namespace for default chat room to `env`.`APP_KEVACOIN_ROOM_NAMESPACE_DEFAULT` (for homepage redirects)
|
||||
|
||||
|
@ -22,7 +22,11 @@ parameters:
|
||||
app.kevacoin.explorer.url: '%env(APP_KEVACOIN_EXPLORER_URL)%'
|
||||
app.kevacoin.mine.pool.url: '%env(APP_KEVACOIN_MINE_POOL_URL)%'
|
||||
app.kevacoin.mine.solo.url: '%env(APP_KEVACOIN_MINE_SOLO_URL)%'
|
||||
app.session.default.timeout: '%env(APP_SESSION_DEFAULT_TIMEOUT)%'
|
||||
app.session.online.timeout: '%env(APP_SESSION_ONLINE_TIMEOUT)%'
|
||||
app.add.user.name.regex: '%env(APP_ADD_USER_NAME_REGEX)%'
|
||||
app.add.user.name.blacklist: '%env(APP_ADD_USER_NAME_BLACKLIST)%'
|
||||
app.add.user.remote.ip.delay: '%env(APP_ADD_USER_REMOTE_IP_DELAY)%'
|
||||
app.add.room.remote.ip.regex: '%env(APP_ADD_ROOM_REMOTE_IP_REGEX)%'
|
||||
app.add.room.remote.ip.delay: '%env(APP_ADD_ROOM_REMOTE_IP_DELAY)%'
|
||||
app.add.room.remote.ip.denied: '%env(APP_ADD_ROOM_REMOTE_IP_DENIED)%'
|
||||
|
@ -44,6 +44,8 @@ body
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* header */
|
||||
|
||||
header
|
||||
{
|
||||
background-color: Canvas;
|
||||
@ -95,6 +97,8 @@ header > form > input[type="text"]
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* main */
|
||||
|
||||
main
|
||||
{
|
||||
display: block;
|
||||
@ -158,6 +162,50 @@ main ul li span > svg
|
||||
float: right;
|
||||
}
|
||||
|
||||
main > form
|
||||
{
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 16px 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
main > form > input[type="text"],
|
||||
main > form > input[type="password"],
|
||||
main > form > textarea
|
||||
{
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
main > form > label
|
||||
{
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
main > form > button
|
||||
{
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
|
||||
main > form > output
|
||||
{
|
||||
color: var(--color-error);
|
||||
display: block;
|
||||
font-weight: bolder;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* footer */
|
||||
|
||||
footer
|
||||
{
|
||||
background-color: Canvas;
|
||||
|
646
src/Controller/UserController.php
Normal file
646
src/Controller/UserController.php
Normal file
@ -0,0 +1,646 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class UserController extends AbstractController
|
||||
{
|
||||
private $_algorithm = PASSWORD_BCRYPT;
|
||||
|
||||
private $_options =
|
||||
[
|
||||
'cost' => 12
|
||||
];
|
||||
|
||||
#[Route(
|
||||
'/user',
|
||||
name: 'user_index',
|
||||
methods:
|
||||
[
|
||||
'GET'
|
||||
]
|
||||
)]
|
||||
public function index(
|
||||
?Request $request
|
||||
): Response
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login'
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/join',
|
||||
name: 'user_join',
|
||||
methods:
|
||||
[
|
||||
'GET'
|
||||
]
|
||||
)]
|
||||
public function join(
|
||||
?Request $request
|
||||
): Response
|
||||
{
|
||||
// Check user session does not exist to continue
|
||||
if (!empty($request->cookies->get('KEVACHAT_SESSION')))
|
||||
{
|
||||
// Redirect to logout
|
||||
return $this->redirectToRoute(
|
||||
'user_logout'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->render(
|
||||
'default/user/join.html.twig',
|
||||
[
|
||||
'request' => $request
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/login',
|
||||
name: 'user_login',
|
||||
methods:
|
||||
[
|
||||
'GET'
|
||||
]
|
||||
)]
|
||||
public function login(
|
||||
?Request $request
|
||||
): Response
|
||||
{
|
||||
// Check user session does not exist to continue
|
||||
if (!empty($request->cookies->get('KEVACHAT_SESSION')))
|
||||
{
|
||||
// Redirect to logout
|
||||
return $this->redirectToRoute(
|
||||
'user_logout'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->render(
|
||||
'default/user/login.html.twig',
|
||||
[
|
||||
'request' => $request
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/logout',
|
||||
name: 'user_logout',
|
||||
methods:
|
||||
[
|
||||
'GET'
|
||||
]
|
||||
)]
|
||||
public function logout(
|
||||
?Request $request
|
||||
): Response
|
||||
{
|
||||
// Connect memcached
|
||||
$memcached = new \Memcached();
|
||||
$memcached->addServer(
|
||||
$this->getParameter('app.memcached.host'),
|
||||
$this->getParameter('app.memcached.port')
|
||||
);
|
||||
|
||||
// Make sure cookies exist
|
||||
if (!empty($request->cookies->get('KEVACHAT_SESSION')) && preg_match('/[A-z0-9]{32}/', $request->cookies->get('KEVACHAT_SESSION')))
|
||||
{
|
||||
// Delete from memory
|
||||
$memcached->delete($session);
|
||||
|
||||
// Delete cookies
|
||||
setcookie('KEVACHAT_SESSION', '', -1);
|
||||
}
|
||||
|
||||
// Redirect to main page
|
||||
return $this->redirectToRoute(
|
||||
'user_login'
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/join',
|
||||
name: 'user_add',
|
||||
methods:
|
||||
[
|
||||
'POST'
|
||||
]
|
||||
)]
|
||||
public function add(
|
||||
Request $request,
|
||||
TranslatorInterface $translator
|
||||
): Response
|
||||
{
|
||||
// Check maintenance mode disabled
|
||||
if ($this->getParameter('app.maintenance'))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Maintenance, please try again later!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Check user session does not exist to continue
|
||||
if (!empty($request->cookies->get('KEVACHAT_SESSION')))
|
||||
{
|
||||
// Redirect to logout
|
||||
return $this->redirectToRoute(
|
||||
'user_logout'
|
||||
);
|
||||
}
|
||||
|
||||
// Trim extra spaces from username
|
||||
$username = trim(
|
||||
$request->get('username')
|
||||
);
|
||||
|
||||
// Connect memcached
|
||||
$memcached = new \Memcached();
|
||||
$memcached->addServer(
|
||||
$this->getParameter('app.memcached.host'),
|
||||
$this->getParameter('app.memcached.port')
|
||||
);
|
||||
|
||||
// Create IP delay record
|
||||
$memory = md5(
|
||||
sprintf(
|
||||
'%s.UserController::add:add.user.remote.ip.delay:%s',
|
||||
__DIR__,
|
||||
$request->getClientIp(),
|
||||
),
|
||||
);
|
||||
|
||||
// Validate remote IP limits
|
||||
if ($delay = (int) $memcached->get($memory))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => sprintf(
|
||||
$translator->trans('Please wait %s seconds before register new username!'),
|
||||
(int) $this->getParameter('app.add.user.remote.ip.delay') - (time() - $delay)
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Check client connection
|
||||
if (!$client = $this->_client())
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not connect wallet database!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Check users database accessible
|
||||
if (!$namespace = $this->_namespace($client))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not access user database, try again later!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate kevacoin key requirements
|
||||
if (mb_strlen($username) < 1 || mb_strlen($username) > 520)
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username length out of KevaCoin protocol limits!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate meta NS
|
||||
if (str_starts_with($username, '_'))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username contain meta format!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username regex
|
||||
if (!preg_match($this->getParameter('app.add.user.name.regex'), $username))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => sprintf(
|
||||
$translator->trans('Username does not match node requirements: %s!'),
|
||||
$this->getParameter('app.add.user.name.regex')
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username blacklist (reserved)
|
||||
if (in_array($username, (array) explode('|', $this->getParameter('app.add.user.name.blacklist'))))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username reserved by node!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username exist
|
||||
if ($this->_hash($client, $namespace, $username))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username already taken!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate password length
|
||||
if (mb_strlen($request->get('password')) <= 12)
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Please, provide stronger password!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate passwords match
|
||||
if ($request->get('password') !== $request->get('repeat'))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Password repeat incorrect!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Generate password hash
|
||||
if (!$hash = password_hash($request->get('password'), $this->_algorithm, $this->_options))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not generate password hash!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Auth success, add user to DB
|
||||
if (!$this->_add($client, $namespace, $username, $hash))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_add',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not create user in blockchain!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Register event time
|
||||
$memcached->set(
|
||||
$memory,
|
||||
time(),
|
||||
(int) $this->getParameter('app.add.user.remote.ip.delay') // auto remove on cache expire
|
||||
);
|
||||
|
||||
// Auth success, create user session
|
||||
$session = md5(
|
||||
sprintf(
|
||||
'%s.%s.%s',
|
||||
$request->get('username'),
|
||||
$request->getClientIp(),
|
||||
rand()
|
||||
)
|
||||
);
|
||||
|
||||
// Save session to memory
|
||||
if (!$memcached->set($session, $request->get('username'), (int) time() + $this->getParameter('app.session.default.timeout')))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not save user session!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Save session to user cookies
|
||||
if (!setcookie('KEVACHAT_SESSION', $session, time() + $this->getParameter('app.session.default.timeout')))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not create session cookie!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Redirect to main page
|
||||
return $this->redirectToRoute(
|
||||
'room_index'
|
||||
);
|
||||
|
||||
// Redirect to login page
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/login',
|
||||
name: 'user_auth',
|
||||
methods:
|
||||
[
|
||||
'POST'
|
||||
]
|
||||
)]
|
||||
public function auth(
|
||||
Request $request,
|
||||
TranslatorInterface $translator
|
||||
): Response
|
||||
{
|
||||
// Check maintenance mode disabled
|
||||
if ($this->getParameter('app.maintenance'))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Maintenance, please try again later!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Check user session does not exist to continue
|
||||
if (!empty($request->cookies->get('KEVACHAT_SESSION')))
|
||||
{
|
||||
// Redirect to logout
|
||||
return $this->redirectToRoute(
|
||||
'user_logout'
|
||||
);
|
||||
}
|
||||
|
||||
// Connect memcached
|
||||
$memcached = new \Memcached();
|
||||
$memcached->addServer(
|
||||
$this->getParameter('app.memcached.host'),
|
||||
$this->getParameter('app.memcached.port')
|
||||
);
|
||||
|
||||
// Check client connection
|
||||
if (!$client = $this->_client())
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not connect wallet database!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Check username namespace accessible
|
||||
if (!$namespace = $this->_namespace($client))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not access user database, try again later!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Trim extra spaces from username
|
||||
$username = trim(
|
||||
$request->get('username')
|
||||
);
|
||||
|
||||
// Validate kevacoin key requirements
|
||||
if (mb_strlen($username) < 1 || mb_strlen($username) > 520)
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username length out of KevaCoin protocol limits!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate meta NS
|
||||
if (str_starts_with($username, '_'))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username contain meta format!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username regex
|
||||
if (!preg_match($this->getParameter('app.add.user.name.regex'), $username))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => sprintf(
|
||||
$translator->trans('Username does not match node requirements: %s!'),
|
||||
$this->getParameter('app.add.user.name.regex')
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username blacklist
|
||||
if (in_array($username, (array) explode('|', $this->getParameter('app.add.user.name.blacklist'))))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username reserved by node!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate username exist
|
||||
if (!$hash = $this->_hash($client, $namespace, $username))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Username not found!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate password
|
||||
if (!password_verify($request->get('password'), $hash))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Password invalid!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Validate password algo
|
||||
if (password_needs_rehash($hash, $this->_algorithm, $this->_options))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Password needs rehash!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Auth success, create user session
|
||||
$session = md5(
|
||||
sprintf(
|
||||
'%s.%s.%s',
|
||||
$request->get('username'),
|
||||
$request->getClientIp(),
|
||||
rand()
|
||||
)
|
||||
);
|
||||
|
||||
// Save session to memory
|
||||
if (!$memcached->set($session, $request->get('username'), (int) time() + $this->getParameter('app.session.default.timeout')))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not save user session!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Save session to user cookies
|
||||
if (!setcookie('KEVACHAT_SESSION', $session, time() + $this->getParameter('app.session.default.timeout')))
|
||||
{
|
||||
return $this->redirectToRoute(
|
||||
'user_login',
|
||||
[
|
||||
'username' => $request->get('username'),
|
||||
'error' => $translator->trans('Could not create session cookie!')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Redirect to main page
|
||||
return $this->redirectToRoute(
|
||||
'room_index'
|
||||
);
|
||||
}
|
||||
|
||||
private function _client(): \Kevachat\Kevacoin\Client
|
||||
{
|
||||
$client = new \Kevachat\Kevacoin\Client(
|
||||
$this->getParameter('app.kevacoin.protocol'),
|
||||
$this->getParameter('app.kevacoin.host'),
|
||||
$this->getParameter('app.kevacoin.port'),
|
||||
$this->getParameter('app.kevacoin.username'),
|
||||
$this->getParameter('app.kevacoin.password')
|
||||
);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
private function _namespace(
|
||||
\Kevachat\Kevacoin\Client $client
|
||||
): ?string
|
||||
{
|
||||
foreach ((array) $client->kevaListNamespaces() as $value)
|
||||
{
|
||||
if ($value['displayName'] === '_KEVACHAT_USERS_')
|
||||
{
|
||||
return $value['namespaceId'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function _hash(
|
||||
\Kevachat\Kevacoin\Client $client,
|
||||
string $namespace,
|
||||
string $username
|
||||
): ?string
|
||||
{
|
||||
if ($user = $client->kevaGet($namespace, $username))
|
||||
{
|
||||
if (!empty($user['value']))
|
||||
{
|
||||
return (string) $user['value'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function _add(
|
||||
\Kevachat\Kevacoin\Client $client,
|
||||
string $namespace,
|
||||
string $username,
|
||||
string $hash
|
||||
): ?string
|
||||
{
|
||||
return $client->kevaPut(
|
||||
$namespace,
|
||||
$username,
|
||||
$hash
|
||||
);
|
||||
}
|
||||
}
|
17
templates/default/user/join.html.twig
Normal file
17
templates/default/user/join.html.twig
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends 'default/layout.html.twig' %}
|
||||
{% block head_title_content %}{{ 'Join' | trans }} - {{ 'KevaChat' | trans }}{% endblock %}
|
||||
{% block main_content %}
|
||||
<form name="join" action="{{ path('user_add') }}" method="post">
|
||||
{% if request.get('error') %}
|
||||
<output name="error">{{ request.get('error') }}</output>
|
||||
{% endif %}
|
||||
<label for="username">{{ 'Username' | trans }}</label>
|
||||
<input type="text" name="username" id="username" value="{{ request.get('username') }}" placeholder="{{ 'Your public identity for this instance, permanently stored in blockchain' | trans }}" />
|
||||
<label for="password">{{ 'Password' | trans }}</label>
|
||||
<input type="password" name="password" id="password" value="" placeholder="{{ 'Bcrypt hash of this password permanently stored in blockchain' | trans }}" />
|
||||
<label for="repeat">{{ 'Repeat password' | trans }}</label>
|
||||
<input type="password" name="repeat" id="repeat" value="" placeholder="{{ 'Make sure your password is correct, you can not reset it later!' | trans }}" />
|
||||
<a href="{{ path('user_login') }}">{{ 'I have account' | trans }}</a>
|
||||
<button type="submit">{{ 'join' | trans }}</button>
|
||||
</form>
|
||||
{% endblock %}
|
15
templates/default/user/login.html.twig
Normal file
15
templates/default/user/login.html.twig
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends 'default/layout.html.twig' %}
|
||||
{% block head_title_content %}{{ 'Login' | trans }} - {{ 'KevaChat' | trans }}{% endblock %}
|
||||
{% block main_content %}
|
||||
<form name="login" action="{{ path('user_auth') }}" method="post">
|
||||
{% if request.get('error') %}
|
||||
<output name="error">{{ request.get('error') }}</output>
|
||||
{% endif %}
|
||||
<label for="username">{{ 'Username' | trans }}</label>
|
||||
<input type="text" name="username" id="username" value="{{ request.get('username') }}" />
|
||||
<label for="password">{{ 'Password' | trans }}</label>
|
||||
<input type="password" name="password" id="password" value="" />
|
||||
<a href="{{ path('user_join') }}">{{ 'Create account' | trans }}</a>
|
||||
<button type="submit">{{ 'login' | trans }}</button>
|
||||
</form>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user