mirror of https://github.com/flarum/flarum
Merge 3c35412e66
into 6916205522
commit
c89fcf6d6e
|
@ -15,13 +15,23 @@
|
|||
"email": "franz@develophp.org"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pipindex/core"
|
||||
},
|
||||
{
|
||||
"type":"vcs",
|
||||
"url": "https://github.com/romanzpolski/flarum-ext-shawTheme"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/flarum/core/issues",
|
||||
"source": "https://github.com/flarum/flarum",
|
||||
"docs": "http://flarum.org/docs"
|
||||
},
|
||||
"require": {
|
||||
"flarum/core": "^0.1.0",
|
||||
"flarum/core": "master",
|
||||
"flarum/flarum-ext-akismet": "^0.1.0",
|
||||
"flarum/flarum-ext-approval": "^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-subscriptions": "^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": {
|
||||
"franzl/studio": "^0.11.0"
|
||||
|
@ -47,6 +62,6 @@
|
|||
"config": {
|
||||
"preferred-install": "dist"
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"minimum-stability": "dev",
|
||||
"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
|
||||
* **Fast**, with a total JS payload size of ~130 KB gzipped
|
||||
* **Extensible**, so you can tailor it to your use-case
|
||||
`launch.php` is a custom script that gives you a reproducable development environment.
|
||||
|
||||

|
||||
## 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