mirror of https://github.com/flarum/flarum
Merge 3c35412e66
into 6916205522
commit
c89fcf6d6e
|
@ -15,13 +15,23 @@
|
||||||
"email": "franz@develophp.org"
|
"email": "franz@develophp.org"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pipindex/core"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type":"vcs",
|
||||||
|
"url": "https://github.com/romanzpolski/flarum-ext-shawTheme"
|
||||||
|
}
|
||||||
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/flarum/core/issues",
|
"issues": "https://github.com/flarum/core/issues",
|
||||||
"source": "https://github.com/flarum/flarum",
|
"source": "https://github.com/flarum/flarum",
|
||||||
"docs": "http://flarum.org/docs"
|
"docs": "http://flarum.org/docs"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^0.1.0",
|
"flarum/core": "master",
|
||||||
"flarum/flarum-ext-akismet": "^0.1.0",
|
"flarum/flarum-ext-akismet": "^0.1.0",
|
||||||
"flarum/flarum-ext-approval": "^0.1.0",
|
"flarum/flarum-ext-approval": "^0.1.0",
|
||||||
"flarum/flarum-ext-auth-facebook": "^0.1.0",
|
"flarum/flarum-ext-auth-facebook": "^0.1.0",
|
||||||
|
@ -39,7 +49,12 @@
|
||||||
"flarum/flarum-ext-sticky": "^0.1.0",
|
"flarum/flarum-ext-sticky": "^0.1.0",
|
||||||
"flarum/flarum-ext-subscriptions": "^0.1.0",
|
"flarum/flarum-ext-subscriptions": "^0.1.0",
|
||||||
"flarum/flarum-ext-suspend": "^0.1.0",
|
"flarum/flarum-ext-suspend": "^0.1.0",
|
||||||
"flarum/flarum-ext-tags": "^0.1.0"
|
"flarum/flarum-ext-tags": "^0.1.0",
|
||||||
|
"wuethrich44/flarum-ext-sso": "^1.1",
|
||||||
|
"romanzpolski/flarum-ext-shawTheme": "*@dev",
|
||||||
|
"sijad/flarum-ext-pages": "dev-master",
|
||||||
|
"davis/flarum-ext-customfooter": "dev-master",
|
||||||
|
"avatar4eg/flarum-ext-users-list": "dev-master"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"franzl/studio": "^0.11.0"
|
"franzl/studio": "^0.11.0"
|
||||||
|
@ -47,6 +62,6 @@
|
||||||
"config": {
|
"config": {
|
||||||
"preferred-install": "dist"
|
"preferred-install": "dist"
|
||||||
},
|
},
|
||||||
"minimum-stability": "beta",
|
"minimum-stability": "dev",
|
||||||
"prefer-stable": true
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
$uri = urldecode(
|
||||||
|
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
|
||||||
|
);
|
||||||
|
$tokens = explode('/', $uri);
|
||||||
|
$handler = __DIR__.'/'.$tokens[1].'.php';
|
||||||
|
if ($uri !== '/' && file_exists(__DIR__.'/'.$uri)) {
|
||||||
|
// If requesting the root page, or raw files/folders
|
||||||
|
// Return as is
|
||||||
|
return false;
|
||||||
|
} elseif (file_exists($handler)) {
|
||||||
|
// This is for /api and /admin
|
||||||
|
include_once $handler;
|
||||||
|
} else {
|
||||||
|
include_once __DIR__.'/index.php';
|
||||||
|
}
|
53
readme.md
53
readme.md
|
@ -1,33 +1,40 @@
|
||||||

|

|
||||||
|
## How to launch with one command?
|
||||||
|
|
||||||
**[Flarum](http://flarum.org) is free, open-source forum software** built with PHP and [Mithril.js](http://mithril.js.org). It is:
|
* Step 1: `composer install`
|
||||||
|
* Step 2: `php -S localhost:9999 launch.php`
|
||||||
|
|
||||||
* **Simple**, with a responsive UI that is optimized for touch devices
|
`launch.php` is a custom script that gives you a reproducable development environment.
|
||||||
* **Fast**, with a total JS payload size of ~130 KB gzipped
|
|
||||||
* **Extensible**, so you can tailor it to your use-case
|
|
||||||
|
|
||||||

|
## SSO Mock
|
||||||
|
|
||||||
## Installation
|
* Step 1: Before you try this out, make sure you paste `6cdVzOYGVW` in the api_keys of the flarum database in MySQL.
|
||||||
|
* Step 2: Create a `config.php` file in the `sso` folder with the contents given at the very bottom.
|
||||||
|
* Step 3: Head to [here](http://localhost:9999/admin#/extensions) and enable *Single Sign On* extension.
|
||||||
|
* Step 4: Fill in the details as shown in the image below.
|
||||||
|
* Step 5: Now, navigate to `sso` folder and run `php -S localhost:8888`
|
||||||
|
* Step 6: Access the sample SSO website on `localhost:8888`
|
||||||
|
|
||||||
> **Flarum is currently in beta and should not be used in production.** It is being developed openly on GitHub. Check out the [Roadmap](http://flarum.org/roadmap) to follow along with our progress.
|

|
||||||
|
|
||||||
You must have SSH access to a server with **PHP 5.5+** and **MySQL 5.5+**, and install [Composer](https://getcomposer.org).
|
|
||||||
|
|
||||||
```
|
```
|
||||||
composer create-project flarum/flarum . --stability=beta
|
<?php
|
||||||
|
return [
|
||||||
|
// URL to your Flarum forum
|
||||||
|
'flarum_url' => 'http://localhost:9999',
|
||||||
|
// Domain of your main site (without http://)
|
||||||
|
'root_domain' => 'localhost',
|
||||||
|
// Create a random key in the api_keys table of your Flarum forum
|
||||||
|
'flarum_api_key' => '6cdVzOYGVW',
|
||||||
|
// Random token to create passwords
|
||||||
|
'password_token' => 'NotSecureToken',
|
||||||
|
// How many days should the login be valid
|
||||||
|
'lifetime_in_days' => 14,
|
||||||
|
];
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Read the [Installation Guide](http://flarum.org/docs/installation) for more information.
|
___
|
||||||
|
* Last revision on 16/09/2017
|
||||||
|
* @aligajani
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
Refer to the [FAQ](http://flarum.org/docs/faq), [Documentation](http://flarum.org/docs), and ask questions on the [Community Forum](http://discuss.flarum.org) or [Gitter Chat](https://gitter.im/flarum/flarum).
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Flarum is open-source and we would love your help building it! Please read the [Contributing Guide](https://github.com/flarum/flarum/blob/master/CONTRIBUTING.md) to learn how you can help.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Copyright (c) 2015 Toby Zerner. Code released under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE).
|
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class SSOController
|
||||||
|
{
|
||||||
|
const REMEMBER_ME_KEY = 'flarum_remember';
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->config = require __DIR__ . '/config.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method after your user is successfully authenticated.
|
||||||
|
*
|
||||||
|
* @param $username
|
||||||
|
* @param $email
|
||||||
|
* @param $avatarUrl
|
||||||
|
*/
|
||||||
|
public function login($username, $email, $avatarUrl)
|
||||||
|
{
|
||||||
|
$password = $this->createPassword($username);
|
||||||
|
$token = $this->getToken($username, $password);
|
||||||
|
|
||||||
|
if (empty($token)) {
|
||||||
|
$this->signup($username, $password, $email, $avatarUrl);
|
||||||
|
$token = $this->getToken($username, $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setRememberMeCookie($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method after you logged out your user.
|
||||||
|
*/
|
||||||
|
public function logout()
|
||||||
|
{
|
||||||
|
$this->removeRememberMeCookie();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirects a user back to the forum.
|
||||||
|
* @param $targetUrl
|
||||||
|
*/
|
||||||
|
public function redirectToForum($targetUrl)
|
||||||
|
{
|
||||||
|
$targetUrl = (!is_null($targetUrl)) ? $targetUrl : '';
|
||||||
|
header('Location: ' . $this->config['flarum_url'] . $targetUrl);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createPassword($username)
|
||||||
|
{
|
||||||
|
return hash('sha256', $username . $this->config['password_token']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToken($username, $password)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'identification' => $username,
|
||||||
|
'password' => $password,
|
||||||
|
'lifetime' => $this->getLifetimeInSeconds(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->sendPostRequest('/api/token', $data);
|
||||||
|
|
||||||
|
return isset($response['token']) ? $response['token'] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function signup($username, $password, $email, $avatarUrl)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
"data" => [
|
||||||
|
"type" => "users",
|
||||||
|
"attributes" => [
|
||||||
|
"username" => $username,
|
||||||
|
"password" => $password,
|
||||||
|
"email" => $email,
|
||||||
|
"avatarUrl" => $avatarUrl
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->sendPostRequest('/api/users', $data);
|
||||||
|
|
||||||
|
return isset($response['data']['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendPostRequest($path, $data)
|
||||||
|
{
|
||||||
|
$data_string = json_encode($data);
|
||||||
|
|
||||||
|
$ch = curl_init($this->config['flarum_url'] . $path);
|
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'Content-Length: ' . strlen($data_string),
|
||||||
|
'Authorization: Token ' . $this->config['flarum_api_key'] . '; userId=1',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
|
return json_decode($result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setRememberMeCookie($token)
|
||||||
|
{
|
||||||
|
$this->setCookie(self::REMEMBER_ME_KEY, $token, time() + $this->getLifetimeInSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeRememberMeCookie()
|
||||||
|
{
|
||||||
|
unset($_COOKIE[self::REMEMBER_ME_KEY]);
|
||||||
|
$this->setCookie(self::REMEMBER_ME_KEY, '', time() - 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCookie($key, $token, $time)
|
||||||
|
{
|
||||||
|
setcookie($key, $token, $time, '/', $this->config['root_domain']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLifetimeInSeconds()
|
||||||
|
{
|
||||||
|
return $this->config['lifetime_in_days'] * 60 * 60 * 24;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('SSOController.php');
|
||||||
|
|
||||||
|
$authToken = $_GET['auth_token'];
|
||||||
|
$targetUrl = (isset($_GET['target_url'])) ? $_GET['target_url'] : null;
|
||||||
|
if (!isset($authToken) || empty($authToken) || $authToken == "") echo 'Login failed';
|
||||||
|
$decodedTestData = json_decode(base64_decode($authToken));
|
||||||
|
|
||||||
|
$email = $decodedTestData->email;
|
||||||
|
$username = $decodedTestData->username;
|
||||||
|
$avatarUrl = $decodedTestData->avatarUrl;
|
||||||
|
|
||||||
|
$forum = new SSOController();
|
||||||
|
$forum->login($username, $email, $avatarUrl);
|
||||||
|
$forum->redirectToForum($targetUrl);
|
|
@ -0,0 +1,216 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<title>Shaw Academy</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
|
||||||
|
|
||||||
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- Leave those next 4 lines if you care about users using IE8 -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
/* Profile container */
|
||||||
|
.profile {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Profile sidebar */
|
||||||
|
.profile-sidebar {
|
||||||
|
padding: 20px 0 10px 0;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-userpic img {
|
||||||
|
float: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
-webkit-border-radius: 50% !important;
|
||||||
|
-moz-border-radius: 50% !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usertitle {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usertitle-name {
|
||||||
|
color: #5a7391;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usertitle-job {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #5b9bd1;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-userbuttons {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-userbuttons .btn {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 1816;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 6px 15px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-userbuttons .btn:last-child {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li {
|
||||||
|
border-bottom: 1px solid #f0f4f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li a {
|
||||||
|
color: #93a3b5;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li a i {
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li a:hover {
|
||||||
|
background-color: #fafcfd;
|
||||||
|
color: #5b9bd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li.active {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-usermenu ul li.active a {
|
||||||
|
color: #5b9bd1;
|
||||||
|
background-color: #f6f9fb;
|
||||||
|
border-left: 2px solid #5b9bd1;
|
||||||
|
margin-left: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Profile Content */
|
||||||
|
.profile-content {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
min-height: 460px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container text-center">
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h3>Hypothetical Phoenix Authenticated Page</h3>
|
||||||
|
<p>A user is logged into members area. Let's demonstrate SSO with Flarum.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<p class="lead">Fake data generated using <strong>faker.js</strong></p>
|
||||||
|
|
||||||
|
<div class="row profile">
|
||||||
|
<div class="col-md-4 col-md-offset-4">
|
||||||
|
<div class="profile-sidebar">
|
||||||
|
|
||||||
|
<div class="profile-userpic">
|
||||||
|
<img class="img-responsive" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="profile-usertitle">
|
||||||
|
<div class="profile-usertitle-name"></div>
|
||||||
|
<div class="profile-usertitle-job"> Developer </div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="profile-userbuttons">
|
||||||
|
<button type="button" class="email btn btn-success btn-sm"></button>
|
||||||
|
</div>
|
||||||
|
<div class="profile-userbuttons">
|
||||||
|
<button type="button" class="username btn btn-danger btn-sm"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="profile-usermenu">
|
||||||
|
<ul class="nav">
|
||||||
|
<li class="active">
|
||||||
|
<a class="visit-link" href="">
|
||||||
|
<i class="glyphicon glyphicon-list"></i>
|
||||||
|
Visit Forum </a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Including Bootstrap JS (with its jQuery dependency) so that dynamic components work -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var randomUsername = faker.internet.userName();
|
||||||
|
var randomAvatar = faker.internet.avatar();
|
||||||
|
var randomEmail = faker.internet.email();
|
||||||
|
var randomName = faker.name.findName();
|
||||||
|
var fake = {
|
||||||
|
dotusername: randomUsername,
|
||||||
|
username: randomUsername.replace('.',''),
|
||||||
|
avatarUrl: randomAvatar,
|
||||||
|
email: randomEmail,
|
||||||
|
name: randomName
|
||||||
|
};
|
||||||
|
var encoded = window.btoa(JSON.stringify(fake));
|
||||||
|
|
||||||
|
console.log(fake);
|
||||||
|
console.log(encoded);
|
||||||
|
|
||||||
|
var targetUrl = "&target_url=/t/parent-tag";
|
||||||
|
var authRedirect = "/auth.php?auth_token=" + encoded + targetUrl;
|
||||||
|
$('.visit-link').attr("href", authRedirect);
|
||||||
|
|
||||||
|
$('.profile-userpic .img-responsive').attr("src", randomAvatar);
|
||||||
|
$('.profile-usertitle-name').html(randomName);
|
||||||
|
$('.container pre').html(authRedirect);
|
||||||
|
$('.username').html(randomUsername);
|
||||||
|
$('.email').html(randomEmail);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('SSOController.php');
|
||||||
|
|
||||||
|
$forum = new SSOController();
|
||||||
|
|
||||||
|
$forum->logout();
|
||||||
|
$forum->redirectToForum();
|
Loading…
Reference in New Issue