Skip to content

Commit 8ce4222

Browse files
authored
Merge pull request #7 from byjg/bump
Bump Version
2 parents 804b9d2 + 0d4ed38 commit 8ce4222

27 files changed

+766
-156
lines changed

.github/workflows/phpunit.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: PHPUnit
2+
on:
3+
push:
4+
branches:
5+
- master
6+
tags:
7+
- "*.*.*"
8+
pull_request:
9+
branches:
10+
- master
11+
12+
jobs:
13+
Build:
14+
runs-on: 'ubuntu-latest'
15+
container: 'byjg/php:${{ matrix.php-version }}-cli'
16+
strategy:
17+
matrix:
18+
php-version:
19+
- "8.1"
20+
- "8.0"
21+
- "7.4"
22+
- "7.3"
23+
- "7.2"
24+
- "7.1"
25+
26+
steps:
27+
- uses: actions/checkout@v2
28+
- run: composer install
29+
- run: ./vendor/bin/phpunit --stderr
30+
31+
Documentation:
32+
runs-on: 'ubuntu-latest'
33+
needs: Build
34+
if: github.ref == 'refs/heads/master'
35+
env:
36+
DOC_GITHUB_TOKEN: '${{ secrets.DOC_TOKEN }}'
37+
steps:
38+
- uses: actions/checkout@v2
39+
- run: curl https://opensource.byjg.com/add-doc.sh | bash /dev/stdin php authuser

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ composer.lock
44
vendor
55
.idea/*
66
!.idea/runConfigurations
7+
.phpunit.result.cache

.travis.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

.vscode/launch.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Debug current Script in Console",
9+
"type": "php",
10+
"request": "launch",
11+
"program": "${file}",
12+
"cwd": "${fileDirname}",
13+
"port": 9003,
14+
"runtimeArgs": [
15+
"-dxdebug.start_with_request=yes"
16+
],
17+
"env": {
18+
"XDEBUG_MODE": "debug,develop",
19+
"XDEBUG_CONFIG": "client_port=${port}"
20+
}
21+
},
22+
{
23+
"name": "PHPUnit Debug",
24+
"type": "php",
25+
"request": "launch",
26+
"program": "${workspaceFolder}/vendor/bin/phpunit",
27+
"cwd": "${workspaceFolder}",
28+
"port": 9003,
29+
"runtimeArgs": [
30+
"-dxdebug.start_with_request=yes"
31+
],
32+
"env": {
33+
"XDEBUG_MODE": "debug,develop",
34+
"XDEBUG_CONFIG": "client_port=${port}"
35+
}
36+
}
37+
]
38+
}

README.md

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# Auth User PHP
22

3+
4+
[![Build Status](https://github.com/byjg/authuser/actions/workflows/phpunit.yml/badge.svg?branch=master)](https://github.com/byjg/authuser/actions/workflows/phpunit.yml)
35
[![Opensource ByJG](https://img.shields.io/badge/opensource-byjg-success.svg)](http://opensource.byjg.com)
46
[![GitHub source](https://img.shields.io/badge/Github-source-informational?logo=github)](https://github.com/byjg/authuser/)
57
[![GitHub license](https://img.shields.io/github/license/byjg/authuser.svg)](https://opensource.byjg.com/opensource/licensing.html)
68
[![GitHub release](https://img.shields.io/github/release/byjg/authuser.svg)](https://github.com/byjg/authuser/releases/)
7-
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/69f04d22-055d-40b5-8c8d-90598a5367b5/mini.png)](https://insight.sensiolabs.com/projects/69f04d22-055d-40b5-8c8d-90598a5367b5)
8-
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/byjg/authuser/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/byjg/authuser/?branch=master)
9-
[![Build Status](https://travis-ci.com/byjg/authuser.svg?branch=master)](https://travis-ci.com/byjg/authuser)
109

1110

1211
A simple and customizable class for enable user authentication inside your application. It is available on XML files, Relational Databases and Moodle.
@@ -139,23 +138,35 @@ If you do not know to create/manage that unique prefix **prefer to use the regul
139138

140139
## Architecture
141140

141+
```text
142+
┌───────────────────┐
143+
│ SessionContext │
144+
└───────────────────┘
145+
146+
┌────────────────────────┐ ┌────────────────────────┐
147+
│ UserDefinition │─ ─ ┐ │ ─ ─ ┤ UserModel │
148+
└────────────────────────┘ ┌───────────────────┐ │ └────────────────────────┘
149+
┌────────────────────────┐ └────│ UsersInterface │────┐ ┌────────────────────────┐
150+
│ UserPropertyDefinition │─ ─ ┘ └───────────────────┘ ─ ─ ┤ UserPropertyModel │
151+
└────────────────────────┘ ▲ └────────────────────────┘
152+
153+
┌────────────────────────┼─────────────────────────┐
154+
│ │ │
155+
│ │ │
156+
│ │ │
157+
┌───────────────────┐ ┌───────────────────┐ ┌────────────────────┐
158+
│ UsersAnyDataset │ │ UsersDBDataset │ │ UsersMoodleDataset │
159+
└───────────────────┘ └───────────────────┘ └────────────────────┘
142160
```
143-
+----------------+ +----------------+
144-
| | | |
145-
| UsersInterface |------------| SessionContext |
146-
| | | |
147-
+----------------+ +----------------+
148-
^
149-
|
150-
|
151-
+-----------------------+--------------------------+
152-
| | |
153-
+-----------------+ +----------------+ +--------------------+
154-
| | | | | |
155-
| UsersAnyDataset | | UsersDBDataset | | UsersMoodleDataset |
156-
| | | | | |
157-
+-----------------+ +----------------+ +--------------------+
158-
```
161+
162+
- UserInterface contain the basic interface for the concrete implementation
163+
- UsersDBDataset is a concrete implementation to retrieve/save user in a Database
164+
- UserAnyDataset is a concrete implementation to retrieve/save user in a Xml file
165+
- UsersMoodleDatabase is a concrete implementation to retrieve users in a Moodle database structure.
166+
- UserModel is the basic model get/set for the user
167+
- UserPropertyModel is the basic model get/set for extra user property
168+
- UserDefinition will map the model to the database
169+
159170

160171
### Database
161172

@@ -213,13 +224,13 @@ $userDefinition = new \ByJG\Authenticate\Definition\UserDefinition(
213224
\ByJG\Authenticate\Model\UserModel::class, // Model class
214225
\ByJG\Authenticate\Definition\UserDefinition::LOGIN_IS_EMAIL,
215226
[
216-
'userid' => 'fieldname of userid',
217-
'name' => 'fieldname of name',
218-
'email' => 'fieldname of email',
219-
'username' => 'fieldname of username',
220-
'password' => 'fieldname of password',
221-
'created' => 'fieldname of created',
222-
'admin' => 'fieldname of admin'
227+
UserDefinition::FIELD_USERID => 'fieldname of userid',
228+
UserDefinition::FIELD_NAME => 'fieldname of name',
229+
UserDefinition::FIELD_EMAIL => 'fieldname of email',
230+
UserDefinition::FIELD_USERNAME => 'fieldname of username',
231+
UserDefinition::FIELD_PASSWORD => 'fieldname of password',
232+
UserDefinition::FIELD_CREATED => 'fieldname of created',
233+
UserDefinition::FIELD_ADMIN => 'fieldname of admin'
223234
]
224235
);
225236
```
@@ -234,23 +245,23 @@ $userDefinition = new \ByJG\Authenticate\Definition\UserDefinition(
234245
\ByJG\Authenticate\Definition\UserDefinition::LOGIN_IS_EMAIL
235246
);
236247

237-
// Defines a custom function to be applied BEFORE update/insert the field 'password'
248+
// Defines a custom function to be applied BEFORE update/insert the field UserDefinition::FIELD_PASSWORD
238249
// $value --> the current value to be updated
239250
// $instance -> The array with all other fields;
240-
$userDefinition->defineClosureForUpdate('password', function ($value, $instance) {
251+
$userDefinition->defineClosureForUpdate(UserDefinition::FIELD_PASSWORD, function ($value, $instance) {
241252
return strtoupper(sha1($value));
242253
});
243254

244-
// Defines a custom function to be applied After the field 'created' is read but before
255+
// Defines a custom function to be applied After the field UserDefinition::FIELD_CREATED is read but before
245256
// the user get the result
246257
// $value --> the current value retrieved from database
247258
// $instance -> The array with all other fields;
248-
$userDefinition->defineClosureForSelect('created', function ($value, $instance) {
259+
$userDefinition->defineClosureForSelect(UserDefinition::FIELD_CREATED, function ($value, $instance) {
249260
return date('Y', $value);
250261
});
251262

252263
// If you want make the field READONLY just do it:
253-
$userDefinition->markPropertyAsReadOnly('created');
264+
$userDefinition->markPropertyAsReadOnly(UserDefinition::FIELD_CREATED);
254265
```
255266

256267

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
"prefer-stable": true,
1111
"require": {
1212
"php": ">=5.6.0",
13-
"byjg/micro-orm": "4.1.*",
14-
"byjg/cache-engine": "4.0.*",
15-
"byjg/jwt-wrapper": "2.0.*"
13+
"byjg/micro-orm": "4.9.*",
14+
"byjg/cache-engine": "4.9.*",
15+
"byjg/jwt-wrapper": "4.9.*"
1616
},
1717
"require-dev": {
18-
"phpunit/phpunit": "5.7.*|7.4.*"
18+
"phpunit/phpunit": "5.7.*|7.4.*|^9.5"
1919
},
2020
"license": "MIT"
2121
}

phpunit.xml.dist

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ and open the template in the editor.
77

88
<!-- see http://www.phpunit.de/wiki/Documentation -->
99
<phpunit bootstrap="./vendor/autoload.php"
10-
colors="false"
10+
colors="true"
11+
testdox="true"
1112
convertErrorsToExceptions="true"
1213
convertNoticesToExceptions="true"
1314
convertWarningsToExceptions="true"
15+
convertDeprecationsToExceptions="true"
1416
stopOnFailure="false">
1517

18+
<php>
19+
<ini name="display_errors" value="On" />
20+
<ini name="display_startup_errors" value="On" />
21+
<ini name="error_reporting" value="E_ALL" />
22+
</php>
23+
1624
<filter>
1725
<whitelist>
1826
<directory>./src</directory>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
namespace ByJG\Authenticate\Definition;
4+
5+
class PasswordDefinition
6+
{
7+
const MINIMUM_CHARS = "minimum_chars";
8+
const REQUIRE_UPPERCASE = "require_uppercase";
9+
const REQUIRE_LOWERCASE = "require_lowercase";
10+
const REQUIRE_SYMBOLS = "require_symbols";
11+
const REQUIRE_NUMBERS = "require_numbers";
12+
const ALLOW_WHITESPACE = "allow_whitespace";
13+
const ALLOW_SEQUENTIAL = "allow_sequential";
14+
const ALLOW_REPEATED = "allow_repeated";
15+
16+
protected $rules = [];
17+
18+
public function __construct($rules = null)
19+
{
20+
$this->rules = [
21+
self::MINIMUM_CHARS => 8,
22+
self::REQUIRE_UPPERCASE => 0, // Number of uppercase characters
23+
self::REQUIRE_LOWERCASE => 1, // Number of lowercase characters
24+
self::REQUIRE_SYMBOLS => 0, // Number of symbols
25+
self::REQUIRE_NUMBERS => 1, // Number of numbers
26+
self::ALLOW_WHITESPACE => 0, // Allow whitespace
27+
self::ALLOW_SEQUENTIAL => 0, // Allow sequential characters
28+
self::ALLOW_REPEATED => 0 // Allow repeated characters
29+
];
30+
foreach ((array)$rules as $rule => $value) {
31+
$this->setRule($rule, $value);
32+
}
33+
}
34+
35+
public function setRule($rule, $value)
36+
{
37+
if (!array_key_exists($rule, $this->rules)) {
38+
throw new \InvalidArgumentException("Invalid rule");
39+
}
40+
$this->rules[$rule] = $value;
41+
}
42+
43+
public function getRules()
44+
{
45+
return $this->rules;
46+
}
47+
48+
public function getRule($rule)
49+
{
50+
if (!array_key_exists($rule, $this->rules)) {
51+
throw new \InvalidArgumentException("Invalid rule");
52+
}
53+
return $this->rules[$rule];
54+
}
55+
56+
public function matchPassword($password)
57+
{
58+
// match password against the rules
59+
if (strlen($password) < $this->rules[self::MINIMUM_CHARS]) {
60+
return false;
61+
}
62+
if ($this->rules[self::REQUIRE_UPPERCASE] > 0) {
63+
if (preg_match_all('/[A-Z]/', $password, $matches) < $this->rules[self::REQUIRE_UPPERCASE]) {
64+
return false;
65+
}
66+
}
67+
if ($this->rules[self::REQUIRE_LOWERCASE] > 0) {
68+
if (preg_match_all('/[a-z]/', $password, $matches) < $this->rules[self::REQUIRE_LOWERCASE]) {
69+
return false;
70+
}
71+
}
72+
if ($this->rules[self::REQUIRE_SYMBOLS] > 0) {
73+
if (preg_match_all('/[!@#$%^&*()\-_=+{};:,<.>]/', $password, $matches) < $this->rules[self::REQUIRE_SYMBOLS]) {
74+
return false;
75+
}
76+
}
77+
if ($this->rules[self::REQUIRE_NUMBERS] > 0) {
78+
if (preg_match_all('/[0-9]/', $password, $matches) < $this->rules[self::REQUIRE_NUMBERS]) {
79+
return false;
80+
}
81+
}
82+
if ($this->rules[self::ALLOW_WHITESPACE] == 0) {
83+
if (preg_match_all('/\s/', $password, $matches) > 0) {
84+
return false;
85+
}
86+
}
87+
if ($this->rules[self::ALLOW_SEQUENTIAL] == 0) {
88+
if (preg_match_all('/([aA][bB][cC]|[bB][cC][dD]|[cC][dD][eE]|[dD][eE][fF]|[eE][fF][gG]|[fF][gG][hH]|[gG][hH][iI]|[hH][iI][jJ]|[iI][jJ][kK]|[jJ][kK][lL]|[kK][lL][mM]|[lL][mM][nN]|[mM][nN][oO]|[nN][oO][pP]|[oO][pP][qQ]|[pP][qQ][rR]|[qQ][rR][sS]|[rR][sS][tT]|[sS][tT][uU]|[tT][uU][vV]|[uU][vV][wW]|[vV][wW][xX]|[wW][xX][yY]|[xX][yY][zZ]|012|123|234|345|456|567|678|789|890|987|876|765|654|543|432|321)/', $password, $matches) > 0) {
89+
return false;
90+
}
91+
92+
}
93+
if ($this->rules[self::ALLOW_REPEATED] == 0) {
94+
if (preg_match_all('/(..?)\1{2,}/', $password, $matches) > 0) {
95+
return false;
96+
}
97+
}
98+
return true;
99+
}
100+
101+
102+
103+
}

0 commit comments

Comments
 (0)