Commit 2e6cda3e authored by Yorre Rajaonarivelo's avatar Yorre Rajaonarivelo
Browse files

activitypub first commit

parent 3e94e09f
......@@ -134,7 +134,7 @@ class ApiController extends Controller
//echo "<script type='text/javascript'> userId = '".Yii::app()->session['userId']."'; var blackfly = 'sosos';</script>";
//managed public and private sections through a url manager
$page = $this->pages[Yii::app()->controller->id][Yii::app()->controller->action->id];
//$page = $this->pages[Yii::app()->controller->id][Yii::app()->controller->action->id];
$headers = getallheaders();
if( isset($headers["X-Auth-Token"]) && isset($headers["X-User-Id"]) && isset($headers["X-Auth-Name"]) && Authorisation::isMeteorConnected( $headers["X-Auth-Token"], $headers["X-User-Id"], $headers["X-Auth-Name"] ) ){
......
<?php
namespace ActivityPub;
class AcceptMessage extends AbstractMessage{
private $message;
use Translate;
use TranslateActivityStream;
public function __construct($actor, $object, $baseUrl){
$domain = parse_url($baseUrl, PHP_URL_HOST);
$this->message = [
"@context" => "https://www.w3.org/ns/activitystreams",
"id" => "https://$domain/".uniqid(),
class AcceptMessage extends Message{
public function __construct($actor, $object){
$data = [
"id" => uniqid(),
"type" => "Accept",
"actor" => $actor,
"object" => $object
];
}
function getReceiver(){
return $this->message["object"]["actor"]."/inbox";
}
function getMessage(){
return $this->message;
}
function getKeyId(){
return $this->message["actor"];
];
$this->content = Translate::convert([$data],TranslateActivityStream::$dataBinding_activity)[0];
$this->receiver = $this->content["object"]["actor"]."/inbox";
$this->actor = $this->content["actor"];
}
}
\ No newline at end of file
<?php
namespace ActivityPub;
use DateTime;
use DateTimeZone;
class Message{
protected $actor;
protected $receiver;
protected $content;
public function __construct($actor=NULL, $receiver=NULL, $content=NULL)
{
$this->actor = $actor;
$this->receiver = $receiver;
$this->content = $content;
}
public function send(){
$targetUrlDomain = parse_url($this->receiver, PHP_URL_HOST);
$targetUrlPath = parse_url($this->receiver, PHP_URL_PATH);
//get current date
$utcDate = new DateTime("now", new DateTimeZone("UTC"));
$utcDateString = $utcDate->format(DateTime::RFC7231);
//get message digest
$digest = Security::digest($this->content);
//define the string to sign
$stringToSign = "(request-target): post $targetUrlPath\nhost: $targetUrlDomain\ndate: $utcDateString\ndigest: SHA-256=$digest";
$signature = Security::sign($stringToSign);
$signature_b64 = base64_encode($signature);
//define the header signature
$headerSignature = 'keyId="'.$this->actor.'",headers="(request-target) host date digest",signature="'.$signature_b64.'"';
//send the message
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->receiver);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Host: ".$targetUrlDomain,
"Date: $utcDateString",
"Digest: SHA-256=$digest",
"Signature: $headerSignature",
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($this->content));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
\ No newline at end of file
......@@ -3,57 +3,73 @@ namespace ActivityPub;
use DateTime;
use DateTimeZone;
use PHDB;
use Translate;
use TranslateActivityStream;
class NoteMessage extends AbstractMessage{
private $message;
private $sender;
private $receiver;
class NoteMessage extends Message{
private $dataToSave = [];
public function __construct($sender, $receiver, $text, $images=[]){
$this->sender = $sender;
$this->receiver = $receiver;
$domain = parse_url($sender, PHP_URL_HOST);
public function __construct($sender, $receivers, $text, $baseUrl = null, $images=[]){
$utcDate = new DateTime("now", new DateTimeZone("UTC"));
$utcDateString = $utcDate->format(DateTime::RFC7231);
$this->message = [
'@context' => 'https://www.w3.org/ns/activitystreams',
'id' => "https://$domain/api/activitypub/m/".uniqid(),
'type' => 'Create',
"actor" => $sender,
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'cc' => [$receiver],
'object' => [
'id' => "https://$domain/api/activitypub/m/".uniqid(),
'type' => 'Note',
'published' => $utcDateString,
'attributedTo' => $sender,
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content'=>"<h1>".$text."</h1>"
]
$noteAttachements = Translate::convert($images, TranslateActivityStream::$dataBinding_attachment);
$noteId = uniqid();
$note = Translate::convert(
array([
"id" => $noteId,
"type" => 'Note',
"published" => $utcDateString,
"attributedTo" => $sender,
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"content" => $text,
"attachment" => $noteAttachements
]),
TranslateActivityStream::$dataBinding_object
)[0];
if($baseUrl)
$note["id"] = $baseUrl.parse_url($note["id"], PHP_URL_PATH);
$this->dataToSave[] = [
"id" => $noteId,
"status" => "outbox",
"data" => $note
];
if(sizeof($images)>0){
$this->message["object"]["attachment"] = [];
foreach($images as $image){
$this->message["object"]["attachment"][] = [
"type" => "Image",
"url"=>$image
];
}
}
}
$activityId = uniqid();
$activity = Translate::convert(
array([
"id" => $activityId,
"type" => "Create",
"actor" => $sender,
"object" => $note,
"to" => ['https://www.w3.org/ns/activitystreams#Public'],
"cc" => $receivers
]),
TranslateActivityStream::$dataBinding_activity
)[0];
if($baseUrl)
$activity["id"] = $baseUrl.parse_url($activity["id"], PHP_URL_PATH);
$this->dataToSave[] = [
"id" => $activityId,
"status" => "outbox",
"data" => $activity
];
function getReceiver(){
return $this->receiver."/inbox";
$this->content = $activity;
$this->actor = $sender;
$this->receivers = $receivers;
}
function getMessage(){
return $this->message;
}
public function send(){
PHDB::batchInsert("activitypub", $this->dataToSave);
function getKeyId(){
return $this->sender;
foreach($this->receivers as $receiver){
$this->receiver = $receiver."/inbox";
parent::send();
}
}
}
\ No newline at end of file
......@@ -5,11 +5,13 @@ use Yii;
class Security{
public static function getPem(){
return [
"private" => file_get_contents(Yii::getAlias('@app')."/certificate/key.pem"),
"public" => file_get_contents(Yii::getAlias('@app')."/certificate/public.pem")
];
public static function getPem($type){
if($type == "private")
return file_get_contents(Yii::getAlias('@app')."/certificate/key.pem");
else if($type == "public")
return file_get_contents(Yii::getAlias('@app')."/certificate/public.pem");
else
return null;
}
public static function digest($message){
......@@ -17,7 +19,7 @@ class Security{
}
public static function sign($stringToSign){
openssl_sign($stringToSign, $signature,self::getPem()["private"], "sha256");
openssl_sign($stringToSign, $signature,self::getPem("private"), "sha256");
return $signature;
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
class ActivitypubController extends ApiController {
public $PRIVATE_KEY = "";
public $PUBLIC_KEY = "";
public $baseUrl = "";
function __construct()
{
......@@ -22,7 +23,8 @@ class ActivitypubController extends ApiController {
'webfinger' => 'api.controllers.activitypub.WebfingerAction',
'person' => 'api.controllers.activitypub.GetActorAction',
'inbox' => 'api.controllers.activitypub.InboxAction',
'message' => 'api.controllers.activitypub.SendMessageAction'
'message' => 'api.controllers.activitypub.SendMessageAction',
'outbox' => 'api.controllers.activitypub.OutboxAction'
);
}
}
\ No newline at end of file
......@@ -8,7 +8,17 @@ class GetActorAction extends CAction{
public function run($u) {
$person = PHDB::findOne(Person::COLLECTION, ["username"=>$u]);
if($person){
$data = Translate::convert([$person], TranslateActivityStream::$dataBinding_actor);
$person["publicKeyPem"] = Security::getPem("public");
$data = Translate::convert([$person], TranslateActivityStream::$dataBinding_actor)[0];
//Only on local dev
if(isset($_SERVER["HTTP_X_ORIGINAL_HOST"])){
$baseUrl = "https://".$_SERVER["HTTP_X_ORIGINAL_HOST"];
$data["id"] = $baseUrl.parse_url($data["id"], PHP_URL_PATH);
$data["inbox"] = $baseUrl.parse_url($data["inbox"], PHP_URL_PATH);
$data["publicKey"]["id"] = $baseUrl.parse_url($data["publicKey"]["id"], PHP_URL_PATH);
}
Rest::json($data);
}else{
echo "No record found for name ".$u;
......
......@@ -5,23 +5,51 @@ use ActivityPub\AcceptMessage;
class InboxAction extends CAction{
public function run() {
public function run($u) {
$data = json_decode(Yii::app()->request->getRawBody(), true);
if(!($person = PHDB::findOne(Person::COLLECTION, ["username"=>$u]))){
echo "user not found";
return;
}
else if(!$data || !isset($data["actor"]) || !($actor = file_get_contents($data["actor"].".json"))){
echo "actor not found";
return;
}
//get server domain
$domain = "64de-102-16-42-138.ngrok.io";//$_SERVER["SERVER_NAME"];
$inboxId = uniqid();
PHDB::insert("activitypub", [
"id" => $inboxId,
"type" => "inbox",
"data" => $data
]);
$actor = json_decode($actor, true);
$object = $data['object'];
$type = $data['type'];
if(is_string($object) && $type == "Follow"){
$username = str_replace("https://$domain/api/activitypub/person/u/","", $object);
$person = PHDB::findOne(Person::COLLECTION, ["username"=>$username]);
$person = PHDB::findOne(Person::COLLECTION, ["username"=>$u]);
if($person){
$message = new AcceptMessage($object, $data, "https://".$domain);
$message->send();
/* $message = new AcceptMessage($object, $data);
$message->send(); */
PHDB::update(Person::COLLECTION, ["username"=>$u], [
'$addToSet' => [
"activityPub.followers"=>[
"ref" => $inboxId,
"actor" => [
"id" => $actor["id"],
"preferredUsername" => $actor["preferredUsername"],
"name" => $actor["name"],
"url" => $actor["url"]
],
"accepted" => false
]
]
]);
}else{
echo "No record found for $username";
echo "No record found for $u";
}
}
}
......
<?php
class OutboxAction extends CAction{
public function run($id) {
$res = PHDB::findOne("activitypub", ["id" => $id]);
if($res)
Rest::json($res["data"]);
else
echo "id not found";
}
}
\ No newline at end of file
......@@ -5,16 +5,21 @@ class SendMessageAction extends CAction{
public function run() {
$message = new NoteMessage(
"https://64de-102-16-42-138.ngrok.io/api/activitypub/person/u/anni",
"https://mastodon.social/users/yorre",
"Blablabla"
);
$message->send();
$user = PHDB::findOneById(Person::COLLECTION, $_SESSION["userId"]);
if(isset($user["activityPub"]["followers"])){
$message = new NoteMessage(
"https://58ba-102-16-43-161.ngrok.io/api/activitypub/person/u/yorre",
$user["activityPub"]["followers"],
"Blablabla",
"https://58ba-102-16-43-161.ngrok.io"
);
$message->send();
}
/* if($result){
PHDB=>=>update(Person=>=>COLLECTION, ["username"=>"anni"], [
'$push'=>[ "followers" => "https=>//mastodon.social/users/yorre" ]
]);
} */
echo "okokok";
}
}
\ No newline at end of file
<?php
class WebfingerAction extends CAction{
public function run(){
$BASE_URL = "http://communecter-dev";
$resource = $_GET["resource"];
$username = preg_replace(['/acct:/', '/@[\s\S]+/'], "", $resource);
if($username){
$person = PHDB::findOne(Person::COLLECTION, ["username"=>$username]);
if($person){
Rest::json([
"subject" => $resource,
"links" => [
[
"rel"=>"self",
"type"=>"application/activity+json",
"href"=> $BASE_URL."/api/activitypub/person/u/".$username
]
]
]);
$data = Translate::convert([["subject" => $resource,"username" => $username]], TranslateActivityStream::$dataBinding_webfinger)[0];
//Only on local dev
if(isset($_SERVER["HTTP_X_ORIGINAL_HOST"])){
$data["links"][0]["href"] = "https://".$_SERVER["HTTP_X_ORIGINAL_HOST"].parse_url($data["links"][0]["href"], PHP_URL_PATH);
}
Rest::json($data);
}else{
echo "No record found for ".$resource;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment