Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120827059
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php
index b6e31296..41ccaf38 100644
--- a/src/app/Http/Controllers/API/SignupController.php
+++ b/src/app/Http/Controllers/API/SignupController.php
@@ -1,168 +1,168 @@
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\SignupCode;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class SignupController extends Controller
{
/**
* Starts signup process.
*
* Verifies user name and email/phone, sends verification email/sms message.
* Returns the verification code.
*
* @param Illuminate\Http\Request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
public function init(Request $request)
{
// Validate user name and email
// TODO: Extended validation and support for phone number
$v = Validator::make(
$request->all(),
[
'email' => 'required|email',
'name' => 'required',
]
);
if ($v->fails()) {
return response()->json(['status' => 'error', 'errors' => $v->errors()], 422);
}
// Generate the verification code
$code = SignupCode::create([
'data' => [
'email' => $request->email,
'name' => $request->name,
]
]);
// TODO: send email/sms message
return response()->json(['status' => 'success', 'code' => $code->code]);
}
/**
* Validation of the verification code.
*
* @param Illuminate\Http\Request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
public function verify(Request $request)
{
// Validate the request args
$v = Validator::make(
$request->all(),
[
'code' => 'required',
'short_code' => 'required',
]
);
if ($v->fails()) {
return response()->json(['status' => 'error', 'errors' => $v->errors()], 422);
}
// Validate the code
$code = SignupCode::find($request->code);
if (empty($code)
|| $code->isExpired()
|| Str::upper($request->short_code) !== Str::upper($code->short_code)
) {
$errors = ['short_code' => "The code is invalid or expired."];
return response()->json(['status' => 'error', 'errors' => $errors], 422);
}
// Return user name and email/phone from the codes database on success
return response()->json([
'status' => 'success',
'email' => $code->data['email'],
'name' => $code->data['name'],
]);
}
/**
* Finishes the signup process by creating the user account.
*
* @param Illuminate\Http\Request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
public function signup(Request $request)
{
// Validate input
$v = Validator::make(
$request->all(),
[
'domain' => 'required|min:3',
'login' => 'required|min:2',
'password' => 'required|min:3|confirmed',
]
);
if ($v->fails()) {
return response()->json(['status' => 'error', 'errors' => $v->errors()], 422);
}
$login = $request->login . '@' . $request->domain;
// TODO: check if specified domain is ours
// TODO: validate login
// Validate verification codes (again)
$v = $this->verify($request);
if ($v->status() !== 200) {
return $v;
}
$code_data = $v->getData();
$user_name = $code_data->name;
$user_email = $code_data->email;
// TODO: check if user with specified login already exists
$user = User::create(
[
// TODO: Save the external email (or phone) ?
'name' => $user_name,
'email' => $login,
'password' => $request->password,
]
);
- $token = auth()->login($user);
-
// Remove the verification code
SignupCode::destroy($request->code);
+ $token = auth()->login($user);
+
return $this->respondWithToken($token);
}
/**
* Get the token array structure.
*
* @param string $token Respond with this token.
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => Auth::guard()->factory()->getTTL() * 60,
]);
}
}
diff --git a/src/resources/vue/components/Signup.vue b/src/resources/vue/components/Signup.vue
index 40243efc..e60d1716 100644
--- a/src/resources/vue/components/Signup.vue
+++ b/src/resources/vue/components/Signup.vue
@@ -1,166 +1,166 @@
<template>
<div class="container">
<div class="card" id="step1">
<div class="card-body">
<h4 class="card-title">Step 1/3</h4>
<p class="card-text">
Sign up to start your free month.
</p>
<form v-on:submit.prevent="submitStep1" data-validation-prefix="signup_">
<div class="form-group">
<label for="signup_name" class="sr-only">Your Name</label>
<input type="text" class="form-control" id="signup_name" placeholder="Your Name" required autofocus v-model="name">
</div>
<div class="form-group">
<label for="signup_email" class="sr-only">Existing Email or Phone Number</label>
<input type="text" class="form-control" id="signup_email" placeholder="Existing Email or Phone Number" required v-model="email">
</div>
<button class="btn btn-primary" type="submit">Continue</button>
</form>
</div>
</div>
<div class="card d-none" id="step2">
<div class="card-body">
<h4 class="card-title">Step 2/3</h4>
<p class="card-text">
We sent out a confirmation code to PHONE/EMAIL.
Enter the code we sent you, or click the link in the message.
</p>
<form v-on:submit.prevent="submitStep2" data-validation-prefix="signup_">
<div class="form-group">
<label for="signup_code" class="sr-only">Confirmation Code</label>
<input type="text" class="form-control" id="signup_code" placeholder="Confirmation Code" required v-model="short_code">
</div>
<button class="btn btn-secondary" type="button" v-on:click="stepBack">Back</button>
<button class="btn btn-primary" type="submit">Continue</button>
</form>
</div>
</div>
<div class="card d-none" id="step3">
<div class="card-body">
<h4 class="card-title">Step 3/3</h4>
<p class="card-text">
Create your Kolab identity (you can choose additional addresses later).
</p>
<form v-on:submit.prevent="submitStep3" data-validation-prefix="signup_">
<div class="form-group">
<label for="signup_login" class="sr-only"></label>
<div class="input-group">
<input type="text" class="form-control" id="signup_login" required>
<span class="input-group-text border-left-0 border-right-0 rounded-0">@</span>
<select class="custom-select rounded-right" id="signup_domain">
<option value="kolabnow.com">kolabnow.com</option>
<option value="kolabnow.com">mykolab.com</option>
</select>
</div>
</div>
<div class="form-group">
<label for="signup_password" class="sr-only">Password</label>
<input type="password" class="form-control" id="signup_password" placeholder="Password" required v-model="password">
</div>
<div class="form-group">
<label for="signup_confirm" class="sr-only">Confirm Password</label>
<input type="password" class="form-control" id="signup_confirm" placeholder="Confirm Password" required v-model="password_confirmation">
</div>
<button class="btn btn-secondary" type="button" v-on:click="stepBack">Back</button>
<button class="btn btn-primary" type="submit">Submit</button>
</form>
</div>
</div>
</div>
</template>
<script>
import store from '../js/store'
export default {
data() {
return {
email: '',
name: '',
code: '',
short_code: '',
password: '',
password_confirmation: ''
}
},
created() {
// Verification code provided, jump to Step 2
if (this.$route.params.code && /^([A-Z0-9]+)-([a-zA-Z0-9]+)$/.test(this.$route.params.code)) {
this.short_code = RegExp.$1
this.code = RegExp.$2
this.submitStep2()
}
},
methods: {
// Submits data to the API, validates and gets verification code
submitStep1() {
this.$root.$emit('clearFormValidation', $('#step1 form'))
axios.post('/api/auth/signup/init', {
email: this.email,
name: this.name
}).then(response => {
$('#step1').addClass('d-none')
$('#step2').removeClass('d-none').find('input').first().focus()
this.code = response.data.code
})
},
// Submits the code to the API for verification
submitStep2() {
this.$root.$emit('clearFormValidation', $('#step2 form'))
axios.post('/api/auth/signup/verify', {
email: this.email,
name: this.name,
code: this.code,
short_code: this.short_code
}).then(response => {
$('#step1,#step2').addClass('d-none')
$('#step3').removeClass('d-none').find('input').first().focus()
$('#signup_domain > option').first().prop('selected', true)
// Reset user name/email, we don't have them if user used a verification link
this.name = response.data.name
this.email = response.data.email
})
},
// Submits the data to the API to create the user account
submitStep3() {
this.$root.$emit('clearFormValidation', $('#step3 form'))
axios.post('/api/auth/signup', {
code: this.code,
short_code: this.short_code,
email: this.email,
// FIXME: For some reason if I use v-model for login and domain fields
// whenever user enters something in login input the domain field
// is reset to an empty value. We'll use jQuery for now
login: $('#signup_login').val(),
domain: $('#signup_domain').val(),
password: this.password,
password_confirmation: this.password_confirmation
}).then(response => {
$('#step2').addClass('d-none')
$('#step3').removeClass('d-none').find('input').first().focus()
- // login user, store the token and redirect to dashboard
+ // auto-login and goto dashboard
store.commit('loginUser')
localStorage.setItem('token', response.data.access_token)
this.$router.push({name: 'dashboard'})
})
},
// Moves the user a step back in registration form
stepBack(e) {
var card = $(e.target).closest('.card')
card.prev().removeClass('d-none')
card.addClass('d-none').find('form')[0].reset()
}
}
}
</script>
diff --git a/src/resources/vue/js/store/index.js b/src/resources/vue/js/store.js
similarity index 100%
rename from src/resources/vue/js/store/index.js
rename to src/resources/vue/js/store.js
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Apr 24, 11:05 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18841818
Default Alt Text
(13 KB)
Attached To
Mode
rK kolab
Attached
Detach File
Event Timeline