How do I get users to enter their username after logging in? - javascript

I want users to enter a username before they get to the dashboard view (if it's the first time they ever logged in) and that "Enter a unique username" will only appear once after their first login and never appear again. I'm not sure do I involve the HomeController and dashboard view(timeline) or not and whether I should just do an #if and #else statement to distinguish between username = null or not.
Home Controller:
use Auth;
class HomeController extends Controller
{
public function index()
{
if (Auth::check()) {
return view('dashboard.index');
}
return view('home');
}
}
This is my User.php:
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $table = 'users';
protected $fillable = [
'username',
'first_name',
'last_name',
'email',
'password',
'location',
'gender',
'date_of_birth',
];
protected $hidden = [
'password',
'remember_token',
];
public function getName()
{
if ($this->first_name && $this->last_name) {
return "{$this->first_name} {$this->last_name}";
}
if ($this->first_name) {
return $this->first_name;
}
return null;
}
public function getUsername()
{
if ($this->first_name && $this->last_name) {
return "{$this->first_name}.{$this->last_name}";
}
if ($this->first_name) {
return $this->first_name;
}
return null;
}
public function getNameOrUsername()
{
return $this->getName() ?: $this->username;
}
public function getUsernameOrName()
{
return $this->getUsername() ?: $this->username;
}
public function getFirstNameOrUsername()
{
return $this->first_name ?: $this->username;
}
}
getusername.blade.php:
<div style="min-width: 800px; margin: 0 auto; position: relative; top: 75px;">
<div class="row" style="width: 600px; margin: 0 auto; border: 2px solid #000; padding: 40px;">
<div class="col-lg-6" style="width: 600px; color: #999; padding: 44.5px 0;">
<h3 style="color: #000; margin-top: 0; margin-bottom: 10px;">Enter a username</h3>
<form class="form-vertical" role="form" method="post" action="{{ route('dashboard.getusername') }}">
<div>
<div>Your public username is the same as your Profile address:
<div>
<ul>
<li>
<div>mostwanted.com/<span id="display_name">
<script>
$('#username').keyup(function () {
$('#display_name').text($(this).val());
});
</script>
</span></div>
</li>
</ul>
</div>
</div>
<div class="form-group {{ $errors->has('username') ? ' has-error' : '' }}">
<label for="username" class="control-label">Choose a username</label>
<input style="width: 456px;" placeholder="e.g. {{ Auth::user()->getUsernameOrName() }}" type="text" name="username" class="form-control" id="username" value="">
#if ($errors->has('username'))
<span class="help-block" style="font-size: 12px; margin-bottom: 0;">{{ $errors->first('username') }}</span>
#endif
</div>
<div>Note: Your username cannot be changed and should include your authentic name </div>
</div>
</div>
<div class="form-group" style="margin-top: 15px;">
<button style="float: right;" type="submit" class="btn btn-primary">Save username</button>
</div>
<input type="hidden" name="_token" value="{{Session::token()}}">
</form>
</div>
</div>
UsernameController:
use Auth;
use DB;
use MostWanted\Models\User;
use Illuminate\Http\Request;
class UsernameController extends Controller
{
public function getUsername()
{
return view('dashboard.getusername');
}
public function postUsername(Request $request)
{
$username = Auth::user()->username;
if (!$username) {
return view('dashboard.getusername');
}
$this->validate($request, [
'username' => 'required|unique:users|regex:/^[A-Za-z0- 9.]+$/|max:50',
]);
User::create([
'username' => $request->input('username'),
]);
return view('dashboard.index');
}
}
The last time I did it was #if (Auth::user()->username===null) it only goes to the form for entering a username even if I've entered a username already (redirect to the username form only).
P.S I have no idea why the <script> doesn't work. I want the <span> to display whatever is being entered in the <input>
EDIT*:
routes.php:
/**
*Home + Entering Username
*/
Route::get('/', [
'uses' => '\MostWanted\Http\Controllers\HomeController#index',
'as' => 'home',
]);
Route::get('/', ['middleware' => 'nousername', function () {
[
'uses' => '\MostWanted\Http\Controllers\UsernameController#getUsername',
'as' => 'dashboard.getusername',
];
[
'uses' => '\MostWanted\Http\Controllers\UsernameController#postUsername',
];
}]);
Route::group(['middleware' => ['web']], function () {
/**
*Authenication
*/
#Sign up
Route::get('/signup', [
'uses' => '\MostWanted\Http\Controllers\AuthController#getSignup',
'as' => 'auth.signup',
'middleware' => ['guest'],
]);
Route::post('/signup', [
'uses' => '\MostWanted\Http\Controllers\AuthController#postSignup',
'middleware' => ['guest'],
]);
#Log in
Route::get('/login', [
'uses' => '\MostWanted\Http\Controllers\AuthController#getSignin',
'as' => 'auth.signin',
'middleware' => ['guest'],
]);
Route::post('/login', [
'uses' => '\MostWanted\Http\Controllers\AuthController#postSignin',
'middleware' => ['guest'],
]);
#Log out
Route::get('/logout', [
'uses' => '\MostWanted\Http\Controllers\AuthController#getSignOut',
'as' => 'auth.signout',
]);
/**
*Search
*/
Route::get('/search', [
'uses' => '\MostWanted\Http\Controllers\SearchController#getResults',
'as' => 'search.results',
]);
/**
*User profile
*/
Route::get('/user/{username}', [
'uses' => '\MostWanted\Http\Controllers\ProfileController#getProfile',
'as' => 'profile.index',
]);
});
NoUsernameMiddleware:
namespace MostWanted\Http\Middleware;
use Auth;
use Closure;
class NoUsernameMiddleware
{
public function handle($request, Closure $next) {
if(!Auth::user()->username) {
return redirect("/choose_username");
}
return $next($request);
}
}

You should use is_null function to test your username
Can you give us the controller's method associated to route('dashboard.getusername') ? Maybe the form works but the username is not saved in database

I suggest you to handle this case with a middleware.
To create one, open the shell in the root of your project and type:
php artisan make:middleware NoUsernameMiddleware
A file called NoUsernameMiddleware.php will be created in app/Http/Middleware/; open it and add these lines in the handle function.
public function handle($request, Closure $next)
{
if(!Auth::user()->username){
return redirect("/path/to/username/input")
}
return $next($request);
}
Register it in app/Http/Kernel.php.
protected $routeMiddleware = [
...,
...,
'nousername' => \App\Http\Middleware\AgeMiddleware::class,
];
Apply the middleware to the dashboard route:
Route::get('/dashboard', ['middleware' => 'nousername', function () {
//
}]);
Then you can create the Controller and the view to handle the form where all of users without an username will be redirected to.

Related

How do I retrieve the values for the select2 dropdowns options from the users table?

I want to retrieve the record of the current user for updating process. For both of the select2 dropdowns, the option listings are correct but I am not getting the right values of role and supervisor as the pre-selected values in each dropdown. What am I missing?
create_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration {
public function up() {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('role');
$table->string('supervisor');
});
}
public function down() {Schema::dropIfExists('users')}
}
update.blade.php
<div><form method="post" action="{{ route('user.update', [$group, $user->id])}}">#csrf
<div>
<label for="name">Name</label>
<div><input id="name" name="name" class="form-control" v-model.trim="$v.user.name.$model"></div>
</div>
<div>
<label for="role">Role</label>
<div class="custom-select2">
<select2 ref="role" id="role" name="role" class="form-control" v-model.trim="$v.user.role.$model">
<option v-for="(opt, index) in role_opt" :selected="opt.role==user.role" :key="opt.role" :value="opt.role">#{{ opt.role }}</option>
</select2>
</div>
</div>
<div>
<label for="supervisor">Supervisor</label>
<div class="custom-select2">
<select2 ref="supervisor" id="supervisor" name="supervisor" class="form-control" v-model.trim="$v.user.supervisor.$model">
<option v-for="(user, index) in userList" :selected="user.id == user.name" :key="user.id" :value="user.name">#{{ user.name }}</option>
</select2>
</div>
</div>
</form></div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data() {
return {
user: #json($json_user),
role_opt: [
{role: 'management', name: 'Management'},
{role: 'employee', name: 'Employee'}
],
userList: [],
}
}
});
</script>
web.php
Route::prefix('user')->group(function () {
Route::get('/', 'UserController#index')->name('user.index');
Route::get('/{group}/', 'UserController#index_group')->name('user.index.group');
Route::get('/ajax/list', 'UserController#user_list')->name('data.user.list');
});
User.php
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable {
protected $fillable = [
'name',
'role',
'supervisor',
];
public function users() {
return $this->belongsToMany('App\User');
}
}
UserController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\UserStoreRequest;
use App\Http\Requests\UserUpdateRequest;
use App\User;
class UserController extends Controller {
public function index_group($group) {
$group_name = '';
if ($group) {
switch ($group) {
case 'admin':
$group_name = 'Admin';
break;
case 'management':
$group_name = 'Management';
break;
case 'employee':
$group_name = 'Employee';
break;
}
}
return view('user.index', compact('group', 'group_name'));
}
public function update($group, $id) {
switch ($group)
{
case 'admin':
$group_name = 'Admin';
break;
case 'management':
$group_name = 'Management';
break;
case 'employee':
$group_name = 'Employee';
break;
default:
abort(404, 'Unknown group');
break;
}
$user = User::findOrFail($id);
$json_user = [
'name' => $user->name,
'role' => $user->role,
'supervisor' => $user->supervisor,
];
return view('user.update', compact('group','group_name','user', 'json_user'));
}
public function user_list() {
$users = User::get();
$data = [];
$data = $users->map(function($item, $index) {
return [
"name" => $item->name,
"role" => $item->role,
"supervisor" => $item->supervisor,
];
});
return $data;
}
}
I believe it could be a case-sensitive issue.
If you change the role_opt[].role to begin with capital letter
role_opt: [
{role: 'Management', name: 'Management'},
{role: 'Employee', name: 'Employee'}
],
OK, if it's not a case sensitive issue, then I believe it has something to do with the <select2 > tag. It is not a standard HTML tag.. and may not understand how to set itself to a 'selected' option. It depends on how you defined the tag.
I think the easiest thing to try for now is change it from <select2> to <select> It should set the default values. If it works, then there is something not quite right with the select2. If it doesn't work, then I would inspect the user object $user = User::findOrFail($id); to ensure everything is exactly as expected.

How to blacklist words in a HTML form?

I was wondering how I am able to blacklist certain words from being entered in my form. Specifically, the username field. I'm not sure if I need access to the PHP/JS files, but I have limited access to those.
<div class="form-group">
<label for="username" class="control-label">{{ lang('signup.username') }}</label>
<input type="text" class="form-control" id="username" value="{{ data['login'] }}" name="RegistrationForm[login]" placeholder="Enter username">'===
</div>
{% if name_fields %}
<script>
function is_banned_name($data) {
$banned_names = array(
'socialwizards', 'socialwizard', 'bulkfollow', 'bulkfollows'
);
foreach($banned_names as $banned_name) {
$pattern = '/('.$banned_name.')/';
$match = preg_match($pattern,$data);
if($match) {
return true;
}
}
return false;
}
if(is_banned_name($_POST['username'])) {
<div class="alert alert-dismissible alert-danger {% if site['rtl'] %} rtl-alert {% endif %}">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ errorMessage }}
</div>
}
</script
(Added this to the end of my form)
You can do it with PHP using javascript is not secure as user can manipulated or disable JavaScript.
function is_banned_name($data) {
$banned_names = array(
'admin', 'test', 'user', 'fake', 'hack', 'error'
);
foreach($banned_names as $banned_name) {
$pattern = '/('.$banned_name.')/';
$match = preg_match($pattern,$data);
if($match) {
return true;
}
}
return false;
}
Then you can say
if(is_banned_name($_POST['username'])) {
// do something
}
You can do it with JavaScript but its not advisable. The code below is an example of how JavaScript code will do it. The code will return true if the name consist of the banned names.
function is_banned_name(str) {
var banned_names = ['admin', 'hacker', 'test', 'user', 'free']; banned_names.forEach(element => {
if(str.match(element)) { return true; }
});
} ```

how do you pass post id in angular?

How do you pass in the post id in angular if your using laravel ?
this is what i currently have, i tried referencing this
https://docs.angularjs.org/api/ng/service/$http
but im not really understanding.
Main.js
$scope.like = function() {
var post = {
// this doesn't work and i dont know how to pull in the post id.
id: "<% $post->id %>"
};
$http.post('post/like/'+ post).success(function(result) {
checkLike();
});
};
function checkLike(){
var post = {
id: "<% $post->id %>"
};
$http.get('post/'+ post '/islikedbyme').success(function(result) {
if (result == 'true') {
$scope.like_btn_text = "Delete Like";
} else {
$scope.like_btn_text = "Like";
}
});
};
Route
Route::get('post/{id}/islikedbyme', 'PostController#isLikedByMe');
Route::post('post/like', 'PostController#like');
Controller
public function isLikedByMe($id)
{
$post = Post::findOrFail($id)->first();
if (Like::whereUserId(Auth::id())->wherePostId($post->id)->exists()){
return 'true';
}
return 'false';
}
public function like(Post $post)
{
$existing_like = Like::withTrashed()->wherePostId($post->id)->whereUserId(Auth::id())->first();
if (is_null($existing_like)) {
Like::create([
'post_id' => $post->id,
'user_id' => Auth::id()
]);
} else {
if (is_null($existing_like->deleted_at)) {
$existing_like->delete();
} else {
$existing_like->restore();
}
}
}
this work i got the post id by using ng-init to pass in post id.
Html
<div id="mypost" class="col-md-8 panel-default" ng-repeat="post in myposts ">
<div id="eli-style-heading" class="panel-heading"><% post.user.name %></div> // i need someway to pull in the post id. so i used ng-init not sure if this best practices.
<div class="panel-body panel" ng-init="getL(post)">
<i style="color:tomato; float:right; font-size:24px;" ng-click="like(post)" class="glyphicon glyphicon-heart"></i>
<figure>
<p ng-model="post.body" editable-text="post.body" e-form="textBtnForm"> <% post.body %></p>
<p name="created_at" ng-model="post.created_at"> <% post.user.created_at | phpDate : "human" %></p>
</figure>
<span>
<i style="color:red;" class="glyphicon glyphicon-remove" ng-click="deletePost(post)" ng-if="post.deletable"></i>
<button ng-if="post.update" class="btn btn-default" ng-click="textBtnForm.$show()" ng-hide="textBtnForm.$visible">
Edit
</button>
<span><button ng-if="post.update" type="submit" class="btn btn-primary" ng-click="updatePost(post)">Update</button></span>
</span>
</div>
</div>
Main.js
$scope.like = function(post) {
$http.post('/post/like/'+ post.id).then(function(result) {
getL();
});
};
$scope.getL = function(post){
$http.get('/post/'+ post.id +'/islikedbyme').then(function(result) {
if (result == 'true') {
$scope.like_btn_text = "Delete Like";
} else {
$scope.like_btn_text = "Like";
}
});
}
Route
Route::get('post/{id}/islikedbyme', 'PostController#isLikedByMe');
Route::post('post/like/{post}', 'PostController#like');
Post Controller
public function like(Post $post, Request $request)
{
$existing_like = Like::withTrashed()->wherePostId($post->id)->whereUserId(auth()->id())->first();
if (is_null($existing_like)) {
Like::create([
'post_id' => $post->id,
'user_id' => auth()->user()->id
]);
} else {
if (is_null($existing_like->deleted_at)) {
$existing_like->delete();
} else {
$existing_like->restore();
}
}
}

Vuejs ajax GET request not returning data in Laravel 5.1 Blade template

am trying to retrieve data from a database using vuejs ajax call with a plugin called vue-resource. Unfortunately, the json data object contains the html page and not the actual data from the database. Can someone please tell me what am doing wrong?
This is my code:
routes.php
<?php
Route::get('find', 'FruitsCtrl#index');
fruitsctrl.php (controller)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Fruit;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome', $fruits);
}
}
fruit.php (model)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Fruit extends Model
{
protected $fillable = [
'id', 'name', 'type'
];
}
fruitshome.blade.php (view)
<head>
<meta id="token" content="{{ csrf_token() }}">
</head>
<body>
<div class="row" id="vapp">
<ul>
<li v-for="fruit in fruits">
#{{ fruit.name }}
#{{ fruit.type }}
</li>
</ul>
</div>
<body>
app.js (javascript)
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
var v = new Vue({
el : "#vapp",
ready :function () {
this.fetchFruits();
},
data : {
fruit : {id:'', name:'', type:''},
fruits : []
},
methods : {
fetchFruits : function(){
this.$http.get('/find').then(function(res){
this.fruits = res;
},function (data){
console.log(error ...);
});
}
}
});
You're currently returning a view from your controller:
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome', $fruits);
}
}
Instead, you can return the Eloquent results directly and they'll be output as JSON:
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return $fruits;
}
}
I think you need to set table name in the model like this :
class Fruit extends Model
{
protected $table = 'fruits';
protected $fillable = [
'id', 'name', 'type'
];
}
You also need to update index method like this :
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome')->withFruits($fruits);
}
and finally update the blade :
<li v-for="fruits in fruit">
#{!! $fruits->name !!}
#{!! $fruits->type !!}
</li>
Let me know if it helps you

Angularjs Satellizer not returning email

I have an app build on angularjs, and laravel and for authentication I use Satellizer.
Currently the login work, but it only return display name. Here is the code:
satellizer.js
providers: {
facebook: {
name: 'facebook',
url: '/auth/facebook',
authorizationEndpoint: 'https://www.facebook.com/v2.3/dialog/oauth',
redirectUri: (window.location.origin || window.location.protocol + '//' + window.location.host) + '/',
requiredUrlParams: ['scope'],
scope: ['email'],
scopeDelimiter: ',',
display: 'popup',
type: '2.0',
popupOptions: { width: 580, height: 400 }
},
account.js
angular.module('MyApp')
.factory('Account', function($http) {
return {
getProfile: function() {
return $http.get('/api/me');
},
updateProfile: function(profileData) {
return $http.put('/api/me', profileData);
}
};
});
profile.js
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">Profile</div>
<div class="panel-body">
<legend><i class="ion-clipboard"></i> Edit My Profile</legend>
<form method="post" ng-submit="updateProfile()">
<div class="form-group">
<label class="control-label">Profile Picture</label>
<img class="profile-picture" ng-src="{{user.picture || 'http://placehold.it/100x100'}}">
</div>
<div class="form-group">
<label class="control-label"><i class="ion-person"></i> Display Name</label>
<input type="text" class="form-control" ng-model="user.displayName" />
</div>
<div class="form-group">
<label class="control-label"><i class="ion-at"></i> Email Address</label>
<input type="email" class="form-control" ng-model="user.email" />
</div>
<button class="btn btn-lg btn-success">Update Information</button>
</form>
</div>
</div>
auth controller in laravel php
public function facebook(Request $request)
{
$accessTokenUrl = 'https://graph.facebook.com/v2.3/oauth/access_token';
$graphApiUrl = 'https://graph.facebook.com/v2.3/me';
$params = [
'code' => $request->input('code'),
'client_id' => $request->input('clientId'),
'redirect_uri' => $request->input('redirectUri'),
'client_secret' => Config::get('app.facebook_secret')
];
$client = new GuzzleHttp\Client();
// Step 1. Exchange authorization code for access token.
$accessToken = $client->get($accessTokenUrl, ['query' => $params])->json();
// Step 2. Retrieve profile information about the current user.
$profile = $client->get($graphApiUrl, ['query' => $accessToken])->json();
// Step 3a. If user is already signed in then link accounts.
if ($request->header('Authorization'))
{
$user = User::where('facebook', '=', $profile['id']);
if ($user->first())
{
return response()->json(['message' => 'There is already a Facebook account that belongs to you'], 409);
}
$token = explode(' ', $request->header('Authorization'))[1];
$payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
$user = User::find($payload['sub']);
dd($user);
$user->facebook = $profile['id'];
$user->displayName = $user->displayName || $profile['name'];
$user->save();
return response()->json(['token' => $this->createToken($user)]);
}
// Step 3b. Create a new user account or return an existing one.
else
{
$user = User::where('facebook', '=', $profile['id']);
if ($user->first())
{
return response()->json(['token' => $this->createToken($user->first())]);
}
$user = new User;
$user->facebook = $profile['id'];
$user->displayName = $profile['name'];
$user->save();
return response()->json(['token' => $this->createToken($user)]);
}
}
Thanks!
In a new Facebook Graph API you should include email and other things you want to get in Graph Api url, take a look at this: https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5
So in your case the solution will be to update your Api urls like this:
Update:
authorizationEndpoint: 'https://www.facebook.com/v2.3/dialog/oauth',
With:
authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth',
And update this:
$accessTokenUrl = 'https://graph.facebook.com/v2.3/oauth/access_token';
$graphApiUrl = 'https://graph.facebook.com/v2.3/me';
With this:
$accessTokenUrl = 'https://graph.facebook.com/v2.5/oauth/access_token';
$graphApiUrl = 'https://graph.facebook.com/v2.5/me?fields=id,name,email,picture,first_name,last_name';

Categories