Kamis 21 November 2019

This commit is contained in:
Damillora 2019-11-21 23:28:57 +07:00
parent 32e983faba
commit fb35b2f5fb
11 changed files with 147 additions and 13 deletions

View File

@ -6,6 +6,9 @@ use Application\HTTP\Response;
use Application\Services\ServiceContainer; use Application\Services\ServiceContainer;
use Application\Models\User; use Application\Models\User;
use Application\Models\UserChange; use Application\Models\UserChange;
use Application\Models\UserConfirmation;
use Application\Foundations\MailBuilder;
use Application\Foundations\QueryBuilder;
class AccountController { class AccountController {
public function __construct() { public function __construct() {
@ -15,6 +18,66 @@ class AccountController {
$user = User::find($request->id); $user = User::find($request->id);
return $response->view('profile', [ 'user' => $user ] ); return $response->view('profile', [ 'user' => $user ] );
} }
public function update_account(Request $request, Response $response) {
$user = ServiceContainer::Authentication()->user();
$hash = $user->password;
$verify = password_verify($request->password,$hash);
if(!$verify) {
return $response->redirect("/me")->with([ "me_error" => "Incorrect password"]);
}
if($request->newpassword) {
if($request->newpassword != $request->confirmpassword) {
return $response->redirect("/me")->with([ "me_error" => "Password and confirm password don't match"]);
}
$confirmator = UserChange::create([
'user_id' => $user->id,
'action_type' => 'password',
'best_before' => date('Y-m-d H:i:s',strtotime("+6 hours")),
'data' => password_hash($request->newpassword,PASSWORD_DEFAULT),
'confirm_key' => hash('sha256',$user->username.time()),
'is_confirmed' => 0,
]);
$email = new MailBuilder();
$body = "Someone, hopefully you, has requested to change your password.\n";
$body .= "To finish the change, use the URL below:\n\n";
$body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/me/confirm?'.$confirmator->confirm_key;
$email->from("metaforums@nanao.moe")->to($user->email)->subject("Confirm important changes to your account")->body($body);
ServiceContainer::Email()->send($email);
}
if (isset($request->email) && $request->email != $user->email) {
$confirmator = UserChange::create([
'user_id' => $user->id,
'action_type' => 'email',
'best_before' => date('Y-m-d H:i:s',strtotime("+6 hours")),
'data' => $request->email,
'confirm_key' => hash('sha256',$user->username.time()),
'is_confirmed' => 0,
]);
$email = new MailBuilder();
$body = "Someone, hopefully you, has requested to change your email.\n";
$body .= "To finish the change, use the URL below:\n\n";
$body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/me/confirm?'.$confirmator->confirm_key;
$body .= "\n\nAfter confirming this change, you need to reconfirm your email address.";
$email->from("metaforums@nanao.moe")->to($user->email)->subject("Confirm important changes to your account")->body($body);
ServiceContainer::Email()->send($email);
}
if (isset($request->delete) && $request->delete == $user->username) {
$confirmator = UserChange::create([
'user_id' => $user->id,
'action_type' => 'delete',
'best_before' => date('Y-m-d H:i:s',strtotime("+6 hours")),
'confirm_key' => hash('sha256',$user->username.time()),
'is_confirmed' => 0,
]);
$email = new MailBuilder();
$body = "Someone, hopefully you, has requested to delete your account.\n";
$body .= "To confirm deletion, use the URL below:\n\n";
$body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/me/confirm?'.$confirmator->confirm_key;
$email->from("metaforums@nanao.moe")->to($user->email)->subject("We are sad to see you leaving")->body($body);
ServiceContainer::Email()->send($email);
}
return $response->redirect("/me");
}
public function update(Request $request, Response $response) { public function update(Request $request, Response $response) {
$user = ServiceContainer::Authentication()->user(); $user = ServiceContainer::Authentication()->user();
$updateData = []; $updateData = [];
@ -35,10 +98,41 @@ class AccountController {
'is_confirmed' => 1, 'is_confirmed' => 1,
]); ]);
} }
$user->update($updateData); $user->update($updateData);
return $response->redirect("/me"); return $response->redirect("/me");
} }
public function confirm(Request $request, Response $response) {
$user = ServiceContainer::Authentication()->user();
$query = new QueryBuilder();
$query = $query->where('confirm_key',$request->queryString())->where('is_confirmed',0);
$change = UserChange::selectOne($query);
if($change) {
if($change->action_type == 'password') {
$user->update(['password' => $change->data]);
} else if($change->action_type == 'email') {
$user->update(['email' => $change->data, 'is_confirmed' => 0]);
$confirmator = UserConfirmation::create([
'confirm_key' => hash('sha256',$user->username.time()),
'user_id' => $user->id,
'best_before' => date('Y-m-d H:i:s', strtotime('+6 hours', time())),
]);
$email = new MailBuilder();
$body = "You have recently changed your email address.\n";
$body .= "You will need to confirm this new address using the URL below:\n\n";
$body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/email/confirm?'.$confirmator->confirm_key;
$email->from("metaforums@nanao.moe")->to($user->email)->subject("Please reconfirm your email address")->body($body);
ServiceContainer::Email()->send($email);
} else if($change->action_type == 'delete') {
$user->update(['is_deactivated' => 1]);
return $response->redirect("/logout");
}
$change->update(['is_confirmed' => 1]);
}
return $response->redirect("/me");
}
public function me(Request $request, Response $response) { public function me(Request $request, Response $response) {
if(!ServiceContainer::Authentication()->isLoggedIn()) return $response->redirect('/login');
$user = ServiceContainer::Authentication()->user(); $user = ServiceContainer::Authentication()->user();
return $response->view('me', [ 'user' => $user ] ); return $response->view('me', [ 'user' => $user ] );
} }

View File

@ -32,10 +32,10 @@ class ApiController {
$bans = $this->getBans(); $bans = $this->getBans();
$where = new QueryBuilder(); $where = new QueryBuilder();
$where = $where->where('group_id',$request->id); $where = $where->where('group_id',$request->id);
$categories = Category::select($where);
if(count($bans) > 0) { if(count($bans) > 0) {
$where = $where->whereNotIn('id',$bans); $where = $where->whereNotIn('id',$bans);
} }
$categories = Category::select($where);
return $response->json()->data($categories); return $response->json()->data($categories);
} }
public function threads(Request $request, Response $response) { public function threads(Request $request, Response $response) {

View File

@ -78,7 +78,7 @@ class AuthController {
$email = new MailBuilder(); $email = new MailBuilder();
$body = "Thank you for registering with metaforums.\n"; $body = "Thank you for registering with metaforums.\n";
$body .= "To be able to explore the vast forum, use the URL below:\n\n"; $body .= "To be able to explore the vast forum, use the URL below:\n\n";
$body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/signup/confirm?'.$confirmator->confirm_key; $body .= $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'].'/email/confirm?'.$confirmator->confirm_key;
$email->from("metaforums@nanao.moe")->to($data->email)->subject("Complete your registration on Metaforums")->body($body); $email->from("metaforums@nanao.moe")->to($data->email)->subject("Complete your registration on Metaforums")->body($body);
ServiceContainer::Email()->send($email); ServiceContainer::Email()->send($email);
if($confirmator != null) { if($confirmator != null) {

View File

@ -9,6 +9,7 @@ use Application\Models\Post;
use Application\Models\Thread; use Application\Models\Thread;
use Application\Models\UserAction; use Application\Models\UserAction;
use Application\Models\UserReport; use Application\Models\UserReport;
use Application\Models\User;
use Application\Foundations\QueryBuilder; use Application\Foundations\QueryBuilder;
use Application\Foundations\MailBuilder; use Application\Foundations\MailBuilder;
@ -82,18 +83,18 @@ class ForumThreadController {
'post_id' => $request->report, 'post_id' => $request->report,
'report_date' => date('Y-m-d H:i:s'), 'report_date' => date('Y-m-d H:i:s'),
]); ]);
if($user->didIModerateThis($category->id)) { if($report->user()->didIModerateThis($category->id)) {
$query = new QueryBuilder(); $query = new QueryBuilder();
$query = $query->where('role','>=','100000'); $query = $query->where('role','>=','100000');
$admins = User::select($query); $admins = User::select($query);
foreach($admins as $moderator) { foreach($admins as $moderator) {
$email = new MailBuilder(); $email = new MailBuilder();
$body = "Dear ".$moderator->username."\n"; $body = "Dear ".$moderator->username."\n";
$body .= "Someone reported ".$report->user()->username.", a moderator for ".$category->category_name." for alleged violation of the rules.\n\n"; $body .= $user->username." reported ".$report->user()->username.", a moderator for ".$category->category_name." for alleged violation of the rules.\n\n";
$body .= "Reason:\n\n"; $body .= "Reason:\n\n";
$body .= $request->content."\n\n"; $body .= $request->content."\n\n";
$body .= "Please resolve this via the moderation interface.\n"; $body .= "Please resolve this via the moderation interface.\n";
$email->from("metaforums@nanao.moe")->to($moderator->email)->subject("New report: ".$user->username)->body($body); $email->from("metaforums@nanao.moe")->to($moderator->email)->subject("New report: ".$report->user()->username)->body($body);
ServiceContainer::Email()->send($email); ServiceContainer::Email()->send($email);
} }
} else { } else {

View File

@ -12,7 +12,7 @@
<p class="">You cannot delete this post.</p> <p class="">You cannot delete this post.</p>
<?php } else if(isset($category) && $auth->user()->is_confirmed == 0 ) { ?> <?php } else if(isset($category) && $auth->user()->is_confirmed == 0 ) { ?>
<p class="">Please confirm your email address to create threads</p> <p class="">Please confirm your email address to create threads</p>
<?php } else if(isset($thread) && $thread->isLocked() ) { ?> <?php } else if(isset($thread) && $thread->isLocked() && !isset($report) ) { ?>
This thread has been locked. This thread has been locked.
<?php } else { ?> <?php } else { ?>
<div id="editor-comp"> <div id="editor-comp">

View File

@ -29,6 +29,28 @@ $view->include('layouts/head');
</div> </div>
</form> </form>
<form method="POST" action="/me/update-account" enctype="multipart/form-data">
<div class="input-group">
<label for="NewPassword">Change Password</label>
<input id="NewPassword" type="password" name="newpassword" value="" placeholder="new password">
<input id="ConfirmPassword" type="password" name="confirmpassword" value="" placeholder="confirm new password">
</div>
<div class="input-group">
<label for="Email">Email</label>
<input id="Email" type="text" name="email" value="<?php echo $user->email ?>" placeholder="email">
</div>
<div class="input-group">
<label for="Delete">Delete Account</label>
<input id="Delete" type="text" name="delete" value="" placeholder="input your username to confirm">
</div>
<div class="input-group">
<label for="Password">Current Password</label>
<input id="Password" type="password" name="password" value="" placeholder="current password">
</div>
<div class="input-group">
<button type="submit">Save</button>
</div>
</form>
</div> </div>
<script src="/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script> <script src="/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>

View File

@ -42,7 +42,7 @@ var selectapp = new Vue({
this.current_category = id; this.current_category = id;
this.current_report = 0; this.current_report = 0;
this.reports = []; this.reports = [];
window.history.pushState('category-'+id,'','<?php echo $root; ?>/moderation?category='+id+window.location.hash); if(id != 0) window.history.pushState('category-'+id,'','<?php echo $root; ?>/moderation?category='+id+window.location.hash);
$.ajax("<?php echo $root; ?>/api/get_reports?id="+id) $.ajax("<?php echo $root; ?>/api/get_reports?id="+id)
.done(function(data) { .done(function(data) {
this.reports = data; this.reports = data;

View File

@ -5,8 +5,8 @@ $view->include('layouts/head');
<div class="forum-post" id="forum-post-<?php echo $post->id ?>"> <div class="forum-post" id="forum-post-<?php echo $post->id ?>">
<div class="forum-post-title"> <div class="forum-post-title">
<p class="text-lg flex-grow"><?php echo $user->username ?>'s profile</p> <p class="text-lg flex-grow"><?php echo $user->username ?>'s profile</p>
<?php if ($auth->isLoggedIn() && $auth->user()->id == $user->id) { ?> <?php if ($auth->isLoggedIn() && ($auth->user()->id == $user->id) ) { ?>
<p class="text-lg px-2"><a href="/me">Edit</a></p> <p class="text-lg px-2"><a class="text-white" href="/me">Edit</a></p>
<?php } ?> <?php } ?>
</div> </div>
<div class="forum-post-content"> <div class="forum-post-content">
@ -50,7 +50,7 @@ $view->include('layouts/head');
</tr> </tr>
<tr> <tr>
<td>Most Active In</td> <td>Most Active In</td>
<td><?php echo $user->most_active()->category_name ?> (<?php echo $user->most_active()->group()->group_name ?>)</td> <td><?php echo $user->most_active()->category_name ?? "None" ?> (<?php echo $user->most_active() ? $user->most_active()->group()->group_name : "None" ?>)</td>
</tr> </tr>
<tr> <tr>
<td>Number of Hearts</td> <td>Number of Hearts</td>

View File

@ -1,7 +1,7 @@
<?php if($thread->isLocked()) { ?> <?php if($thread->isLocked()) { ?>
<div class="lock-message"> <div class="lock-message">
This thread has been locked for <?php echo $thread->lock()->duration ?>. See the last post for reason why. This thread has been locked for <?php echo $thread->lock()->duration ?>. See the last post for reason why.
<?php if($auth->user()->didIModerateThis($thread->category_id) ) { ?> <?php if($auth->isLoggedIn() && $auth->user()->didIModerateThis($thread->category_id) ) { ?>
<a href="/thread/unlock?id=<?php echo $thread->id ?>">Unlock this thread</a> <a href="/thread/unlock?id=<?php echo $thread->id ?>">Unlock this thread</a>
<?php } ?> <?php } ?>
</div> </div>
@ -71,7 +71,7 @@ This thread has been locked for <?php echo $thread->lock()->duration ?>. See the
<a class="forum-post-footer-action" @click="report(<?php echo $post->id ?>)">Report Abuse</a> <a class="forum-post-footer-action" @click="report(<?php echo $post->id ?>)">Report Abuse</a>
<?php } ?> <?php } ?>
<?php } ?> <?php } ?>
<?php if($auth->user()->didIModerateThis($thread->category()->id) ) { ?> <?php if($auth->user()->didIModerateThis($thread->category()->id) || $auth->user()->is_admin ) { ?>
<a class="forum-post-footer-action" @click="moderate(<?php echo $post->id ?>)">Moderate</a> <a class="forum-post-footer-action" @click="moderate(<?php echo $post->id ?>)">Moderate</a>
<?php } ?> <?php } ?>
<?php } ?> <?php } ?>
@ -92,16 +92,19 @@ var threadapp = new Vue({
$.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&reply="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&reply="+post_id).done(function(data) {
$("#editor").html(data); $("#editor").html(data);
}); });
window.location.hash = "#editor";
}, },
edit(post_id) { edit(post_id) {
$.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&edit="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&edit="+post_id).done(function(data) {
$("#editor").html(data); $("#editor").html(data);
}); });
window.location.hash = "#editor";
}, },
delete_post(post_id) { delete_post(post_id) {
$.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&delete="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&delete="+post_id).done(function(data) {
$("#editor").html(data); $("#editor").html(data);
}); });
window.location.hash = "#editor";
}, },
favorite(post_id) { favorite(post_id) {
$.ajax("<?php echo $root ?>/api/favorite?id="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/api/favorite?id="+post_id).done(function(data) {
@ -113,11 +116,13 @@ var threadapp = new Vue({
$.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&report="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/thread/editor?thread=<?php echo $thread->id ?>&report="+post_id).done(function(data) {
$("#editor").html(data); $("#editor").html(data);
}); });
window.location.hash = "#editor";
}, },
moderate(post_id) { moderate(post_id) {
$.ajax("<?php echo $root ?>/thread/moderating_editor?id="+post_id).done(function(data) { $.ajax("<?php echo $root ?>/thread/moderating_editor?id="+post_id).done(function(data) {
$("#editor").html(data); $("#editor").html(data);
}); });
window.location.hash = "#editor";
} }
}, },
}); });

View File

@ -10,7 +10,9 @@ An online web-based discussion forum application
4. Point the browser to `localhost` 4. Point the browser to `localhost`
## Sample database data ## Sample database data
### Users ### Users
1. Username: Administrator 1. Username: Administrator
Password: yuikaadmin Password: yuikaadmin
Role: Site Admin Role: Site Admin
@ -32,6 +34,10 @@ An online web-based discussion forum application
7. Username: MusubiTendouji 7. Username: MusubiTendouji
Password: nanasisters Password: nanasisters
Role: User Role: User
8. Username: BadEnd
Password: communicate
Role: User
### Post sources ### Post sources

View File

@ -9,7 +9,7 @@ return [
'POST:/signup' => [ 'POST:/signup' => [
'controller' => 'AuthController@create_user', 'controller' => 'AuthController@create_user',
], ],
'GET:/signup/confirm' => [ 'GET:/email/confirm' => [
'controller' => 'AuthController@sign_up_confirm', 'controller' => 'AuthController@sign_up_confirm',
], ],
'GET:/login' => [ 'GET:/login' => [
@ -75,6 +75,12 @@ return [
'POST:/me/update' => [ 'POST:/me/update' => [
'controller' => 'AccountController@update', 'controller' => 'AccountController@update',
], ],
'POST:/me/update-account' => [
'controller' => 'AccountController@update_account',
],
'GET:/me/confirm' => [
'controller' => 'AccountController@confirm',
],
'GET:/moderation' => [ 'GET:/moderation' => [
'controller' => 'IndexController@moderation', 'controller' => 'IndexController@moderation',
], ],