Skip to content

Commit 39fc60f

Browse files
committed
Add commands, routes. Update CHANGELOG
1 parent 1abba32 commit 39fc60f

18 files changed

+3856
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor

CHANGELOG.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased](https://gitlab.devsep.com/septech-php/septech-laravel/snowflake/-/compare/v1.0.2...master)
78

8-
## [Unreleased](https://gitlab.devsep.com/septech-php/septech-laravel/snowflake/-/compare/v1.0.0...master)
9+
## [v1.0.2 - 2020-09-01](https://github.com/SepteniTechnology/laravel-snowflake/compare/v1.0.1...v1.0.2)
10+
### Changed
11+
- Update URL to github
912

10-
## [v1.0.1 - 2020-08-24](https://gitlab.devsep.com/septech-php/septech-laravel/snowflake/-/compare/v1.0.0...v1.0.1)
13+
### Added
14+
- MIT license
15+
- Built-in middleware
16+
- Intergrated phpunit
17+
- Added routes
18+
- Added `SNOWFLAKE_HTTP_TOKEN` env variable
19+
- Added `worker:token` command
20+
21+
22+
## [v1.0.1 - 2020-08-24](https://github.com/SepteniTechnology/laravel-snowflake/compare/v1.0.0...v1.0.1)
1123
### Added
1224
- Add facades
1325

14-
## [v1.0.0 - 2020-08-21](https://gitlab.devsep.com/septech-php/septech-laravel/snowflake/-/tree/v1.0.0)
26+
27+
## [v1.0.0 - 2020-08-21](https://github.com/SepteniTechnology/laravel-snowflake/tree/v1.0.0)
1528
### Added
1629
- Release version 1.0 🚀🚀🚀

Console/Commands/Env.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Septech\Snowflake\Console\Commands;
4+
5+
class Env
6+
{
7+
protected $filepath;
8+
9+
protected $attributes = [];
10+
11+
public function __construct($filepath)
12+
{
13+
$this->filepath = $filepath;
14+
}
15+
16+
public function get($key, $default = null)
17+
{
18+
return env($key, $default);
19+
}
20+
21+
public function has($key)
22+
{
23+
return env($key, $this) !== $this;
24+
}
25+
26+
public function replace($key, $value)
27+
{
28+
$replacement = sprintf("/^\s*($key)\s*=\s*(.*)?\s*$/m", $key);
29+
30+
file_put_contents($this->filepath, preg_replace(
31+
$replacement,
32+
$key.'='.$value,
33+
file_get_contents($this->filepath)
34+
));
35+
}
36+
37+
public function put($key, $value)
38+
{
39+
$this->has($key) ? $this->replace($key, $value) : $this->write($key, $value);
40+
}
41+
42+
public function write($key, $value)
43+
{
44+
file_put_contents($this->filepath, sprintf("%s=%s\n", $key, $value), FILE_APPEND);
45+
}
46+
}

Console/Commands/WorkerAllocateCommand.php

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,34 +32,25 @@ public function handle()
3232

3333
$instanceId = AllocatedWorker::allocateFor($machineId);
3434

35-
if (! $this->hasEnvironment('SNOWFLAKE_WORKER_ID')) {
35+
$env = new Env($this->laravel->environmentFilePath());
36+
37+
if (! $env->has('SNOWFLAKE_WORKER_ID')) {
3638
$workerId = AllocatedWorker::workerId($instanceId);
3739

3840
$this->info("Assigning worker:" . json_encode(["machine_id" => $machineId, 'worker_id' => $workerId]));
39-
$this->putEnvironment('SNOWFLAKE_WORKER_ID', $workerId);
41+
$env->write('SNOWFLAKE_WORKER_ID', $workerId);
4042
}
4143

42-
if (! $this->hasEnvironment('SNOWFLAKE_DATACENTER_ID')) {
44+
if (! $env->has('SNOWFLAKE_DATACENTER_ID')) {
4345
$dataCenterId = AllocatedWorker::dataCenterId($instanceId);
4446

4547
$this->info("Assigning data center:" . json_encode(["machine_id" => $machineId, 'data_center_id' => $dataCenterId]));
46-
$this->putEnvironment('SNOWFLAKE_DATACENTER_ID', $dataCenterId);
48+
$env->write('SNOWFLAKE_DATACENTER_ID', $dataCenterId);
4749
}
4850

4951
$this->info('OK');
5052
}
5153

52-
protected function putEnvironment($key, $value)
53-
{
54-
$envPath = app()->environmentFilePath();
55-
file_put_contents($envPath, sprintf("%s=\"%s\"\n", $key, $value), FILE_APPEND);
56-
}
57-
58-
protected function hasEnvironment($key)
59-
{
60-
return env($key, $this) !== $this;
61-
}
62-
6354
protected function getInstanceId()
6455
{
6556
if (app()->environment('local')) {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Septech\Snowflake\Console\Commands;
4+
5+
use Illuminate\Support\Str;
6+
use Illuminate\Console\Command;
7+
8+
class WorkerTokenCommand extends Command
9+
{
10+
protected $signature = 'worker:token {--force : Overrides the generated token}';
11+
12+
protected $description = 'Generate server token using to release & assign worker via API';
13+
14+
public function handle()
15+
{
16+
$env = new Env($this->laravel->environmentFilePath());
17+
18+
$write = ! $env->has("SNOWFLAKE_HTTP_TOKEN") || $this->option('force');
19+
20+
if ($write || $this->confirm("The token was assigned. Do you want overrides it?")) {
21+
$token = Str::random(64);
22+
23+
$env->put("SNOWFLAKE_HTTP_TOKEN", $token);
24+
25+
$this->line("Token: <comment>$token</comment>");
26+
$this->info("Application key set successfully.");
27+
}
28+
}
29+
}

Facades/Snowflake.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ public static function next()
1919
{
2020
return static::getFacadeRoot()->id();
2121
}
22+
23+
public static function routes()
24+
{
25+
require_once __DIR__ . '/../routes.php';
26+
}
2227
}

Http/Controllers/AllocatedWorkerController.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Septech\Snowflake\Http\Controllers;
44

5-
use Septech\Http\Response;
65
use Illuminate\Http\Request;
76
use Illuminate\Foundation\Validation\ValidatesRequests;
87
use Septech\Snowflake\AllocatedWorker;
@@ -19,9 +18,12 @@ public function allocate(Request $request)
1918

2019
$instanceId = AllocatedWorker::allocateFor($data['machine_id']);
2120

22-
return Response::success([
23-
'worker_id' => AllocatedWorker::workerId($instanceId),
24-
'data_center_id' => AllocatedWorker::dataCenterId($instanceId),
21+
return response()->json([
22+
'ok' => true,
23+
'data' => [
24+
'worker_id' => AllocatedWorker::workerId($instanceId),
25+
'data_center_id' => AllocatedWorker::dataCenterId($instanceId),
26+
],
2527
]);
2628
}
2729

@@ -33,6 +35,8 @@ public function release(Request $request)
3335

3436
AllocatedWorker::release($data['machine_id']);
3537

36-
return Response::ok();
38+
return response()->json([
39+
'ok' => true
40+
]);
3741
}
3842
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Septech\Snowflake\Http\Middleware;
4+
5+
use Closure;
6+
use Illuminate\Http\Request;
7+
8+
class ServerToken
9+
{
10+
/**
11+
* Handle an incoming request.
12+
*
13+
* @param Request $request
14+
* @param Closure $next
15+
* @return mixed
16+
*/
17+
public function handle(Request $request, Closure $next)
18+
{
19+
$secret = config('snowflake.sever_to_server_token');
20+
$token = $request->header('Authorization');
21+
22+
if ($token) {
23+
// Remove Bearer text
24+
$token = substr($token, 7);
25+
}
26+
27+
if (! $token) {
28+
$token = $request->get('token');
29+
}
30+
31+
if ($token !== $secret) {
32+
abort(403);
33+
}
34+
35+
return $next($request);
36+
}
37+
}

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) Septeni Technology
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44

55
```php
66
composer require septech-laravel/snowflake
7+
8+
# Public config
9+
php artisan vendor:publish --provider="Septech\\Snowflake\\SnowflakeServiceProvider"
10+
```
11+
12+
## Environment
13+
14+
```
15+
16+
#
17+
SNOWFLAKE_EPOCH="2019-07-01 00:00:00"
18+
719
```
820

921
## Usages
@@ -17,3 +29,77 @@ Snowflake::id();
1729
Snowflake::parseId('6696174721395998720');
1830

1931
```
32+
33+
## Zookeeper
34+
35+
To use the Zookeeper we need a DB connection to keep tracking assigned IDs & machine owned that ID.
36+
37+
### Migration database
38+
39+
```sh
40+
# Migrate database schema
41+
php artisan migrate
42+
43+
# Assign the worker id to .env for current marchine.
44+
# It will take the hostname from AWS or get the hostname by gethostname()
45+
php artisan worker:allocate
46+
```
47+
48+
### API
49+
50+
51+
#### Register routes
52+
53+
```php
54+
// -- routes/api.php
55+
use Septech\Snowflake\Facades\Snowflake;
56+
57+
Snowflake::routes();
58+
```
59+
60+
#### Wrap routes within group
61+
62+
```php
63+
use Septech\Snowflake\Facades\Snowflake;
64+
65+
Route::group(['prefix' => '/snowflake'], function () {
66+
Snowflake::routes();
67+
});
68+
69+
```
70+
71+
#### Apply the built-in middleware
72+
73+
We provides a simple middleware to protect the API. The middleware will take token from the `Authorization` header. Or from $_GET['token'] or $_POST['token']. Then compare with a secret key set by config `snowflake.sever_to_server_token` or `env('SNOWFLAKE_HTTP_TOKEN')`. You can set the key manually or run command
74+
75+
```
76+
php artisan worker:token
77+
```
78+
79+
**Force it to override**
80+
```
81+
php artisan worker:token --force
82+
```
83+
84+
```php
85+
Route::group(['middleware' => \Septech\Snowflake\Http\Middleware\ServerToken::class], function () {
86+
Snowflake::routes();
87+
});
88+
89+
```
90+
91+
#### Using Kernel routeMiddleware
92+
93+
```php
94+
// app/Http/Kernel.php
95+
protected $routeMiddleware = [
96+
// ...
97+
'server_token' => \Septech\Snowflake\Http\Middleware\ServerToken::class
98+
// ...
99+
];
100+
101+
// routes/api.php
102+
Route::group(['middleware' => 'server_token'], function () {
103+
Snowflake::routes();
104+
});
105+
```

SnowflakeServiceProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Foundation\Application;
88
use Illuminate\Support\ServiceProvider;
99
use Septech\Snowflake\Console\Commands\WorkerAllocateCommand;
10+
use Septech\Snowflake\Console\Commands\WorkerTokenCommand;
1011

1112
class SnowflakeServiceProvider extends ServiceProvider
1213
{
@@ -26,7 +27,7 @@ public function register()
2627
], 'snowflake');
2728

2829
// Register commands
29-
$this->commands([WorkerAllocateCommand::class]);
30+
$this->commands([WorkerAllocateCommand::class, WorkerTokenCommand::class]);
3031
}
3132

3233
protected function registerSnowflakeInstance()

0 commit comments

Comments
 (0)