Skip to content

Commit

Permalink
Merge branch 'master' of github.com:spira/spira into hotfix/email-change
Browse files Browse the repository at this point in the history
# By Johan Steen (61) and Zak Henry (19)
# Via Johan Steen (7) and others
* 'master' of github.com:spira/spira: (80 commits)
  Defines zip dists for all repositories
  Uses https instead of ssh for all repositories
  Dropped duplicate comment
  Added %expose_port% so the QA runner can rewrite the compose file to it's desired port
  Added docker-compose files for build and prod, reconfigured the qa file to use services
  Extracted out common-services to a separate file
  Bumped bower version for angular-jwt-auth
  Fixed auth test to use correct cookie name
  Added forum redirection, fixed the bower versions to stop master from failing
  Restored .gitkeep file
  Bumped lodash version up, added resolution
  Fixed sso integration test to use cookie name constant
  Upgraded lodash, changed cookie name, implemented config for saving of the cookie to the top level domain.
  Reverted to ~1.4
  Attempting with latest animation update
  Upgrade to angular ~1.4
  Switched forum port to 80, removed proxypass
  Removes cookie generation
  Sets a Database placeholder entry
  Restored hhvm
  ...

# Conflicts:
#	api/tests/integration/UserTest.php
  • Loading branch information
zakhenry committed Aug 17, 2015
2 parents 84ed1cf + f573505 commit 3b26cd5
Show file tree
Hide file tree
Showing 59 changed files with 3,742 additions and 217 deletions.
14 changes: 0 additions & 14 deletions .local.env

This file was deleted.

15 changes: 15 additions & 0 deletions .travis.yml
Expand Up @@ -7,10 +7,23 @@ addons:

services:
- redis-server
- mysql

env:
global:
- VANILLADATABASE_ENV_MYSQL_DATABASE=vanilla
- VANILLADATABASE_PORT_3306_TCP_ADDR=127.0.0.1
- VANILLADATABASE_ENV_MYSQL_USER=travis
- VANILLADATABASE_ENV_MYSQL_PASSWORD=
- VANILLA_JSCONNECT_CLIENT_ID=a-client-id-random-string
- VANILLA_JSCONNECT_SECRET=a-secret-phrase-random-string
- VANILLA_SERVER_HOST=127.0.0.1
- VANILLA_SERVER_PORT=8008

before_install:
- sudo apt-get update -qq
- sudo apt-get install -y libnotify-bin beanstalkd
- mysql -e 'create database vanilla;'

install:
# Install phantomjs@2.0.0 (remove this when https://github.com/travis-ci/travis-ci/issues/3225 is resolved)
Expand All @@ -25,6 +38,7 @@ install:
- travis_retry npm install --no-spin
- travis_retry gulp bower:install
- travis_retry composer self-update
- travis_retry composer install --no-interaction --working-dir forum
- travis_retry composer install --prefer-source --no-interaction --working-dir api
- travis_retry composer install --prefer-source --no-interaction
- travis_retry gem install mailcatcher
Expand All @@ -35,6 +49,7 @@ before_script:
- gulp build
- php ./api/artisan migrate --seed
- php ./api/artisan serve --port 8000 --host 127.0.0.1 --quiet 2>&1 >/dev/null & # start api server
- php -S 127.0.0.1:8008 -t ./forum/public >& /dev/null & # start forum server
- http-server ./app/build/ -p 8001 2>&1 >/dev/null & # start webserver
- mailcatcher # start mailcatcher server
- beanstalkd -d -l 127.0.0.1 -p 11300 # start queue listener
Expand Down
2 changes: 1 addition & 1 deletion api/.travis.env
Expand Up @@ -35,4 +35,4 @@ MAIL_FROM_ADDRESS=api@local.api.spira.io
MAIL_FROM_NAME=spira API

LOG_UDP_HOST=logs2.papertrailapp.com
LOG_UDP_PORT=57202
LOG_UDP_PORT=57202
13 changes: 11 additions & 2 deletions api/app/Extensions/Socialite/Parsers/AbstractParser.php
Expand Up @@ -7,6 +7,8 @@

abstract class AbstractParser implements Arrayable
{
use UsernameTrait;

/**
* User object to parse.
*
Expand All @@ -19,7 +21,7 @@ abstract class AbstractParser implements Arrayable
*
* @var array
*/
protected $attributes = ['token', 'email', 'first_name', 'last_name', 'avatar_img_url'];
protected $attributes = ['token', 'email', 'username', 'first_name', 'last_name', 'avatar_img_url'];

/**
* Initialize the parser.
Expand Down Expand Up @@ -80,9 +82,16 @@ protected function parse()
$this->attributes = array_fill_keys($this->attributes, '');

foreach (array_keys($this->attributes) as $attribute) {
// Get the attribute
$method = camel_case('get_'.$attribute.'_attribute');
if (method_exists($this, $method)) {
$this->attributes[$attribute] = $this->$method();
$this->attributes[$attribute] = $value = $this->$method();
}

// Filter the attribute
$method = camel_case('filter_'.$attribute.'_attribute');
if (method_exists($this, $method)) {
$this->attributes[$attribute] = $this->$method($value);
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions api/app/Extensions/Socialite/Parsers/FacebookParser.php
Expand Up @@ -24,6 +24,16 @@ protected function getEmailAttribute()
return $this->user->email;
}

/**
* Get the user's username.
*
* @return string
*/
protected function getUsernameAttribute()
{
return $this->user->name;
}

/**
* Get the user's first name.
*
Expand Down
10 changes: 10 additions & 0 deletions api/app/Extensions/Socialite/Parsers/GoogleParser.php
Expand Up @@ -24,6 +24,16 @@ protected function getEmailAttribute()
return $this->user->email;
}

/**
* Get the user's username.
*
* @return string
*/
protected function getUsernameAttribute()
{
return $this->user->name;
}

/**
* Get the user's first name.
*
Expand Down
10 changes: 10 additions & 0 deletions api/app/Extensions/Socialite/Parsers/TwitterParser.php
Expand Up @@ -24,6 +24,16 @@ protected function getEmailAttribute()
return $this->user->email;
}

/**
* Get the user's username.
*
* @return string
*/
protected function getUsernameAttribute()
{
return $this->user->nickname;
}

/**
* Get the user's first name.
*
Expand Down
145 changes: 145 additions & 0 deletions api/app/Extensions/Socialite/Parsers/UsernameTrait.php
@@ -0,0 +1,145 @@
<?php

namespace App\Extensions\Socialite\Parsers;

use App\Models\User;

trait UsernameTrait
{
/**
* Get the user's username.
*
* @return string
*/
abstract protected function getUsernameAttribute();

/**
* Define filter for usernames.
*
* @param string $username
*
* @return string
*/
protected function filterUsernameAttribute($username)
{
if ($this->usernameIsUnique($username)) {
return $username;
}

return $this->makeUsernameUnique($username);
}

/**
* Check if the username is unique.
*
* @param string $username
*
* @return bool
*/
protected function usernameIsUnique($username)
{
return ! (bool) User::username($username)->get()->count();
}

/**
* Make sure that the username is unique for Spira.
*
* The username retrieved from the social provider is not guaranteed to be
* unique for Spira. So to ensure a seamless social signup and signin
* process, modify the username if it is not unique to be unique.
*
* @param string $username
*
* @return string
*/
protected function makeUsernameUnique($username)
{
// Try prettye methods first, ordered by priority
$methods = [
'removeSpaces',
'replaceSpacesWithDots',
'switchFirstLast',
'InitialAndLast'
];

foreach ($methods as $method) {
$method = camel_case('username_'.$method);
if (method_exists($this, $method)) {
$tryName = $this->$method($username);

if ($this->usernameIsUnique($tryName)) {
return $tryName;
}
}
}

// None of the pretty methods were successful, start numbering
$suffix = 1;
do {
$tryName = $username.' '.$suffix;
$suffix++;
} while (!$this->usernameIsUnique($tryName));

return $tryName;
}

/**
* Removes spaces from username.
*
* @param string $username
*
* @return string
*/
protected function usernameRemoveSpaces($username)
{
return str_replace(' ', '', $username);
}

/**
* Removes spaces from username.
*
* @param string $username
*
* @return string
*/
protected function usernameReplaceSpacesWithDots($username)
{
return str_replace(' ', '.', $username);
}

/**
* Switch position of first and last name.
*
* @param string $username
*
* @return string
*/
protected function usernameSwitchFirstLast($username)
{
$segments = explode(' ', $username);
if (count($segments) == 2) {
return implode(' ', array_reverse($segments));
}

// The username was not suitable for this operation, return unmodified
return $username;
}

/**
* Use first name initial and last name.
*
* @param string $username
*
* @return string
*/
protected function usernameInitialAndLast($username)
{
$segments = explode(' ', $username);
if (count($segments) == 2) {
return $segments[0][0].$segments[1];
}

// The username was not suitable for this operation, return unmodified
return $username;
}
}
33 changes: 29 additions & 4 deletions api/app/Http/Controllers/AuthController.php
Expand Up @@ -17,13 +17,15 @@
use App\Http\Transformers\AuthTokenTransformer;
use App\Exceptions\UnprocessableEntityException;
use Illuminate\Contracts\Foundation\Application;
use App\Services\SingleSignOn\SingleSignOnFactory;
use App\Extensions\Socialite\Parsers\ParserFactory;
use Laravel\Socialite\Contracts\Factory as Socialite;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\Models\User;

class AuthController extends EntityController
{
const JWT_AUTH_TOKEN_COOKIE = 'ngJwtAuthToken';
/**
* The application instance.
*
Expand Down Expand Up @@ -122,11 +124,9 @@ private function attemptLogin($credentials)
/**
* Refresh a login token.
*
* @param Request $request
*
* @return ApiResponse
*/
public function refresh(Request $request)
public function refresh()
{
$token = $this->jwtAuth->getTokenFromRequest();

Expand Down Expand Up @@ -241,7 +241,32 @@ public function handleProviderCallback($provider, Socialite $socialite, UserRepo
}

/**
* Check so the provider exists.
* Provide a requester with user information for single sign on.
*
* @param string $requester
* @param Request $request
*
* @return Response
*/
public function singleSignOn($requester, Request $request)
{
// A single sign on request might have different requirements and
// methods how to deal with a non logged in user. So we get the user
// if possible, and if not we pass in a null user and let the the
// requester class deal with it according to the requester's definitions
if ($token = $request->cookie(self::JWT_AUTH_TOKEN_COOKIE)) {
$user = $this->jwtAuth->toUser($token);
} else {
$user = null;
}

$requester = SingleSignOnFactory::create($requester, $request, $user);

return $requester->getResponse();
}

/**
* Check so the social provider exists.
*
* @param string $provider
*
Expand Down
2 changes: 2 additions & 0 deletions api/app/Http/routes.php
Expand Up @@ -83,4 +83,6 @@

$app->get('social/{provider}', 'AuthController@redirectToProvider');
$app->get('social/{provider}/callback', 'AuthController@handleProviderCallback');

$app->get('sso/{requester}', 'AuthController@singleSignOn');
});

0 comments on commit 3b26cd5

Please sign in to comment.