List of commits:
Subject Hash Author Date (UTC)
Initial Commit 15c32a418d14fba9a89e0a9dd5bfa283fb5811d4 EyadMohammedOsama 2019-08-16 00:04:14
Added several new methods 0bc95876af1041a053fbb426dfa3c5fb4600647b EyadMohammedOsama 2019-08-16 00:03:27
Initial Commit c1a0c0ceaf232bec3dd3faa0c5d49cf4f840f364 EyadMohammedOsama 2019-08-15 16:18:26
Initial Commit 34400f91e493a86b1a8e0a1e32bc74cfb546c681 EyadMohammedOsama 2019-08-13 23:04:27
Added download button b2778c1c6ed5e42de7bac6ae9223facf33469b8e EyadMohammedOsama 2019-08-08 22:17:29
Initial Commit 31265bb888791eb58829bdf07222d319a3387629 EyadMohammedOsama 2019-08-08 22:17:19
Added router for downloads 700b80e06b8b1809135fe32c0072beb7542570c6 EyadMohammedOsama 2019-08-08 22:17:08
Fiddle favoriting event implementation 5ea13953d8fdd949d122ff3d63bc427d2ac78a43 EyadMohammedOsama 2019-08-07 23:21:04
Added a trigger to fiddle favoriting 435bb1aacd90b540e822b68858a665955e7b6f35 EyadMohammedOsama 2019-08-07 23:20:20
Added Pusher.js ca81b2a591c04e678e415c3fdf10a41a3a11ac62 EyadMohammedOsama 2019-08-07 23:18:08
Configured broadcasting 61ad3285cfc37dfb4265874cf7b3496992846f7e EyadMohammedOsama 2019-08-07 23:17:36
Installed PHP Pusher 85bd7fa0401d69eff36ea21fa6bb60f28601ac14 EyadMohammedOsama 2019-08-07 23:16:31
Initial commit 4a865759d403eda3854c69005a3cfdbd7d737096 EyadMohammedOsama 2019-08-05 21:13:21
Added several new routes 85e08b7120e6ba249f3ecd523234c72f5c19c1cc EyadMohammedOsama 2019-08-05 21:12:53
Added several new routes ba3fca128d64c47fa0e9c8c08fd5e0a6635b08ae EyadMohammedOsama 2019-08-04 23:15:44
Configured sessions table 749fa85c728ab023aee73bff8f08677063edc70a EyadMohammedOsama 2019-08-04 23:15:19
Added a file system to store avatars e260a81485424f72c8a5154a91d5f7c83e180af5 EyadMohammedOsama 2019-08-04 23:15:00
Added new validation rules 42c291c0cbc2181e1fd9cf87991fded5550512cf EyadMohammedOsama 2019-08-04 23:14:36
Added new controllers c7a9229044be1d910911b89a6a049c0e0b4bd3a9 EyadMohammedOsama 2019-08-04 23:14:08
Added new helper file d4d3fd48a15af64a3abaffee411ecf542670be9b EyadMohammedOsama 2019-08-04 23:13:20
Commit 15c32a418d14fba9a89e0a9dd5bfa283fb5811d4 - Initial Commit
Author: EyadMohammedOsama
Author date (UTC): 2019-08-16 00:04
Committer name: EyadMohammedOsama
Committer date (UTC): 2019-08-16 00:04
Parent(s): 0bc95876af1041a053fbb426dfa3c5fb4600647b
Signing key:
Tree: d0de3d1981380fc374c8f61e03ddab86e8e54279
File Lines added Lines deleted
app/Http/Controllers/Reset.php 70 0
app/Http/Controllers/ResetPassword.php 73 0
resources/views/Mail/ResetPassword.blade.php 6 0
resources/views/Reset.blade.php 96 0
resources/views/ResetPassword.blade.php 29 30
File app/Http/Controllers/Reset.php added (mode: 100644) (index 0000000..2496d13)
1 <?php
2
3 namespace SICSF\Http\Controllers;
4
5 use Illuminate\Http\Request;
6 use SICSF\UsersTokens;
7 use Illuminate\Support\Facades\Validator;
8 use SICSF\Users;
9
10 class Reset extends Controller
11 {
12 /**
13 * Handle the incoming request.
14 *
15 * @param \Illuminate\Http\Request $request
16 * @return \Illuminate\Http\Response
17 */
18 public function __invoke(Request $request, $token = "")
19 {
20 if ($request->isMethod("GET")) {
21 $okay = NULL;
22 $username = NULL;
23 $info = UsersTokens::GetTokenInfo($token);
24 $now = date_timestamp_get(date_create());
25 if ($info === NULL || $now > $info->ExpirationDate) {
26 $okay = FALSE;
27 }
28 else {
29 $okay = TRUE;
30 }
31
32 return view("Layout/Template", [
33 "title" => "SICSF - Reset your password",
34 "view" => "Reset",
35 "okay" => $okay,
36 "token" => $token
37 ]);
38 }
39 else if ($request->isMethod("POST")) {
40 $Password = $request->input("password");
41 $PasswordConfirmation = $request->input("password-confirmation");
42 $Token = $request->input("token");
43
44
45 $validator = Validator::make($request->all(), [
46 "password" => "required|min:8|max:1024",
47 "password-confirmation" => "required|min:8|max:1024|same:password"
48 ]);
49
50 if ($validator->fails()) {
51 return response()->json([
52 "errors" => $validator->errors()->all()
53 ]);
54 }
55
56 if (UsersTokens::GetTokenInfo($Token) === NULL) {
57 return response()->json([
58 "errors" => ["The used token is invalid, non-existent, or maybe expired."]
59 ]);
60 }
61
62 $Username = UsersTokens::GetTokenInfo($Token)->Username;
63 Users::UpdatePassword($Username, $Password);
64 UsersTokens::ClearConfirmationToken($Token);
65 return response()->json([
66 "success" => "Your password has been changed successfully."
67 ]);
68 }
69 }
70 }
File app/Http/Controllers/ResetPassword.php added (mode: 100644) (index 0000000..d0312c2)
1 <?php
2
3 namespace SICSF\Http\Controllers;
4
5 use Illuminate\Http\Request;
6 use Illuminate\Support\Facades\Validator;
7 use SICSF\Users;
8 use SICSF\UsersTokens;
9 use Illuminate\Support\Facades\Mail;
10
11 class ResetPassword extends Controller
12 {
13 /**
14 * Handle the incoming request.
15 *
16 * @param \Illuminate\Http\Request $request
17 * @return \Illuminate\Http\Response
18 */
19 public function __invoke(Request $request)
20 {
21 if ($request->isMethod("GET")) {
22 return view("Layout/Template", [
23 "title" => "SICSF - Reset password",
24 "view" => "ResetPassword"
25 ]);
26 }
27 else if ($request->isMethod("POST")) {
28 $validator = Validator::make($request->all(), [
29 "username" => "required|min:6|max:20|regex:/^([A-Za-z0-9_]){6,20}$/i",
30 "email" => "required|email"
31 ]);
32
33 if ($validator->fails()) {
34 return response()->json([
35 "errors" => $validator->errors()->all()
36 ]);
37 }
38
39 $Username = $request->input("username");
40 $Email = $request->input("email");
41
42 if (!Users::UsernameExists($Username)) {
43 return response()->json([
44 "errors" => ["The entered username doesn't belong to any registered user."]
45 ]);
46 }
47
48 if (!Users::EmailExists($Email) || !Users::UsernameBelongsToEmail($Username, $Email)) {
49 return response()->json([
50 "success" => ["If the entered E-mail exist and is already registered, it will recieve a reset password message."]
51 ]);
52 }
53
54 $token = base64_encode(bin2hex(random_bytes(32)));
55
56 Mail::send("Mail/ResetPassword", [
57 "username" => $Username,
58 "token" => $token
59 ], function($message) use ($Username, $Email) {
60 $message
61 ->to($Email, $Username)
62 ->subject("Reset password request");
63 $message->from("noreply@sicsf.heliohost.org", "SICSF Syria");
64 });
65
66 UsersTokens::AddConfirmationToken($Username, $token);
67
68 return response()->json([
69 "success" => ["If the entered E-mail exist and is already registered, it will recieve a reset password message."]
70 ]);
71 }
72 }
73 }
File resources/views/Mail/ResetPassword.blade.php added (mode: 100644) (index 0000000..33de452)
1 <h1>Hello {{ $username }}</h1>
2 <p>It seems you've forgot your password.</p>
3 <p>Please use the following link to change your password:</p>
4 <a href="{{ URL::to('reset/' . $token) }}">{{ URL::to('reset/' . $token) }}</a>
5 <p>If you haven't requested to change your password, please ignore this message.</p>
6 <p>Notice that the above link is only valid for 8 hours.</p>
File resources/views/Reset.blade.php added (mode: 100644) (index 0000000..d0d8e4c)
1 <h1 class="text-center">SICSF - Password reset</h1>
2 <br/>
3 <div class="container-fluid">
4 <div class="row">
5 <div class="col-xs-2 col-sm-2 col-md-3 col-lg-3"></div>
6 <div class="col-xs-8 col-sm-8 col-md-6 col-lg-6 {{ ($okay) ? ('border border-dark rounded') : ('')}}">
7 <br/>
8 @if($okay)
9 <form id="reset-form">
10 <div class="form-group">
11 <div class="row">
12 <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5">
13 <p>Enter your password:</p>
14 </div>
15 <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7">
16 <input type="password" class="form-control" id="password">
17 </div>
18 </div>
19 </div>
20
21 <div class="form-group">
22 <div class="row">
23 <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5">
24 <p>Confirm your password:</p>
25 </div>
26 <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7">
27 <input type="password" class="form-control" id="password-confirmation">
28 </div>
29 </div>
30 </div>
31 <button class="btn btn-block btn-dark">Set new password</button>
32 <br/>
33 <div id="result"></div>
34 </form>
35 <script>
36 $(document).ready(function() {
37 $("#reset-form").on("submit", function(e) {
38 e.preventDefault();
39 var Password = $("#password").val();
40 var PasswordConfirmation = $("#password-confirmation").val();
41
42 var PasswordPattern = /^([\S\s]){8,1024}$/;
43 var IsValid = true;
44 var Message = "";
45
46 if (!PasswordPattern.test(Password)) {
47 IsValid = false;
48 Message += "Password must be at least 8 characters and at most 1024 characters in length.<br>";
49 }
50
51 if (Password !== PasswordConfirmation) {
52 IsValid = false;
53 Message += "Password and its confirmation doesn't match.<br/>";
54 }
55
56 if (!IsValid) {
57 Message = "<div class='alert alert-danger'>" + Message + "</div>";
58 $("#result").html(Message);
59 }
60 else {
61 $.ajax({
62 type : "POST",
63 url : "{{ URL::to('reset') }}",
64 data : {
65 "_token" : window.CSRFHashToken,
66 "token" : "{{ $token }}",
67 "password" : Password,
68 "password-confirmation" : PasswordConfirmation
69 },
70 success : function(result, status, xhr) {
71 if ("errors" in result) {
72 $("#result").html("<div class='alert alert-danger'>" + result.errors.join("<br/>") + "</div>");
73 }
74 else {
75 $("#result").html("<div class='alert alert-success'>" + result.success + "</div>");
76 window.setTimeout(function() {
77 window.location.href = "{{ URL::to('/login') }}";
78 }, 3000);
79 }
80 },
81 error : function(xhr, status, error) {
82 $("#result").html("<div class='alert alert-danger'>An internal error has occured.<br>Please try again later.</div>")
83 }
84 });
85 }
86 });
87 });
88 </script>
89 @else
90 <div class="alert alert-danger text-center">Expired or non-existent token.<br/>Maybe you should request another <a href="{{ URL::to('reset-password') }}">Reset E-mail</a></div>
91 @endif
92 </div>
93 <div class="col-xs-2 col-sm-2 col-md-3 col-lg-3"></div>
94 </div>
95 </div>
96 <br/>
File resources/views/ResetPassword.blade.php copied from file resources/views/Login.blade.php (similarity 67%) (mode: 100644) (index c284080..e129ca7)
2 2 <div class="row"> <div class="row">
3 3 <div class="col-xs-2 col-sm-2 col-md-3 col-lg-3"></div> <div class="col-xs-2 col-sm-2 col-md-3 col-lg-3"></div>
4 4 <div class="col-xs-8 col-sm-8 col-md-6 col-lg-6 border border-dark rounded"> <div class="col-xs-8 col-sm-8 col-md-6 col-lg-6 border border-dark rounded">
5 <h2 class="text-center">Login to your account</h2>
5 <h2 class="text-center">Reset your password</h2>
6 6 <br/> <br/>
7 <form id="login-form">
7 <form id="reset-form">
8 8 <div class="form-group"> <div class="form-group">
9 9 <div class="row"> <div class="row">
10 10 <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5"> <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5">
11 <p>Enter your E-mail:</p>
11 <p>Enter your username:</p>
12 12 </div> </div>
13 13 <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7"> <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7">
14 <input type="email" class="form-control" id="email">
14 <input type="text" class="form-control" id="username">
15 15 </div> </div>
16 16 </div> </div>
17 17 </div> </div>
18
18
19 19 <div class="form-group"> <div class="form-group">
20 20 <div class="row"> <div class="row">
21 21 <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5"> <div class="col-xs-6 col-sm-6 col-md-5 col-lg-5">
22 <p>Enter your password:</p>
22 <p>Enter your E-mail:</p>
23 23 </div> </div>
24 24 <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7"> <div class="col-xs-6 col-sm-6 col-md-7 col-lg-7">
25 <input type="password" class="form-control" id="password">
25 <input type="email" class="form-control" id="email">
26 26 </div> </div>
27 27 </div> </div>
28 28 </div> </div>
29
30 <button class="btn btn-block btn-dark">Login</button>
29 <br/>
30 <br/>
31 <button class="btn btn-block btn-dark">Reset password</button>
31 32 <br/> <br/>
32 33 <div id="result"></div> <div id="result"></div>
33 34 </form> </form>
 
39 40
40 41 <script> <script>
41 42 $(document).ready(function() { $(document).ready(function() {
42 $("#login-form").on("submit", function(e) {
43 $("#reset-form").on("submit", function(e) {
43 44 e.preventDefault(); e.preventDefault();
45 var Username = $("#username").val();
44 46 var Email = $("#email").val(); var Email = $("#email").val();
45 var Password = $("#password").val();
46
47
48 var UsernamePattern = /^([A-Za-z0-9_]){6,20}$/;
47 49 var EmailPattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; var EmailPattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
48 var PasswordPattern = /^([\S\s]){8,}$/;
49 50 var IsValid = true; var IsValid = true;
50 51 var Message = ""; var Message = "";
51
52 if (!EmailPattern.test(Email)) {
52
53 if (!UsernamePattern.test(Username)) {
53 54 IsValid = false; IsValid = false;
54 Message += "E-mail cannot be empty, and must be formatted correctly.<br>";
55 Message += "Username cannot be empty, it must be between 6 and 20 characters in length, and cannot contain anything but letters (A-Z a-z) and numbers (0-9) and underscore (_).";
55 56 } }
56 57
57 if (!PasswordPattern.test(Password)) {
58 if (!EmailPattern.test(Email)) {
58 59 IsValid = false; IsValid = false;
59 Message += "Password must be at least 8 characters in length.<br>";
60 Message += "E-mail cannot be empty, and must be formatted correctly.<br>";
60 61 } }
61
62
62 63 if (!IsValid) { if (!IsValid) {
63 64 Message = "<div class='alert alert-danger'>" + Message + "</div>"; Message = "<div class='alert alert-danger'>" + Message + "</div>";
64 65 $("#result").html(Message); $("#result").html(Message);
 
66 67 else { else {
67 68 $.ajax({ $.ajax({
68 69 type : "POST", type : "POST",
69 url : "{{ URL::to('login') }}",
70 url : "{{ URL::to('reset-password') }}",
70 71 data : { data : {
71 72 "_token" : window.CSRFHashToken, "_token" : window.CSRFHashToken,
72 "email" : Email,
73 "password" : Password,
73 "username" : Username,
74 "email" : Email
74 75 }, },
75 76 success : function(result, status, xhr) { success : function(result, status, xhr) {
76 77 if ("errors" in result) { if ("errors" in result) {
77 if (Array.isArray(result.errors)) {
78 $("#result").html("<div class='alert alert-danger'>" + result.errors.join("<br/>") + "</div>");
79 }
80 else {
81 $("#result").html("<div class='alert alert-danger'>" + result.errors + "</div>")
82 }
78 $("#result").html("<div class='alert alert-danger'>" + result.errors.join("<br/>") + "</div>");
83 79 } }
84 80 else { else {
85 $("#result").html("<div class='alert alert-success'>" + result.success + "</div>");
81 $("#result").html("<div class='alert alert-success'>" + result.success.join("<br/>") + "</div>");
82 window.setTimeout(function() {
83 window.location.href = "{{ URL::to('/') }}";
84 }, 3000);
86 85 } }
87 86 }, },
88 87 error : function(xhr, status, error) { error : function(xhr, status, error) {
89 $("#result").html("<div class='alert alert-danger'>An internal error has occured.<br>Please try again later.</div>")
88 $("#result").html("<div class='alert alert-danger'>An internal error has occured.<br>Please try again later.</div>");
90 89 } }
91 90 }); });
92 91 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/EyadMohammedOsama/sicsf

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/EyadMohammedOsama/sicsf

Clone this repository using git:
git clone git://git.rocketgit.com/user/EyadMohammedOsama/sicsf

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main