Skip to content
This repository was archived by the owner on Oct 24, 2022. It is now read-only.

Commit 11fe687

Browse files
committed
feat: initial commit
1 parent 60070ea commit 11fe687

File tree

14 files changed

+16685
-0
lines changed

14 files changed

+16685
-0
lines changed

.github/workflows/build_and_check.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3+
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [ "master", "main" ]
9+
pull_request:
10+
branches: [ "master", "main" ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
strategy:
17+
matrix:
18+
php-version: [7.4, 8.0]
19+
20+
steps:
21+
- uses: actions/checkout@v2
22+
- name: Cache Composer dependencies
23+
uses: actions/cache@v2
24+
with:
25+
path: /tmp/composer-cache
26+
key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }}
27+
- name: Install dependencies
28+
uses: php-actions/composer@v5
29+
with:
30+
php_version: ${{ matrix.php-version }}
31+
version: 2
32+
php_extensions: json
33+
- name: Run easy coding standard
34+
run: vendor/bin/ecs check
35+
release:
36+
name: Release
37+
needs: [build]
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v2
42+
with:
43+
fetch-depth: 0
44+
- name: Setup Node.js
45+
uses: actions/setup-node@v1
46+
with:
47+
node-version: 14
48+
- name: Release
49+
env:
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
run: npm install && npx semantic-release

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# IntelliJ project files
2+
.idea
3+
*.iml
4+
out
5+
gen
6+
modules
7+
node_modules
8+
vendor/
9+
composer.lock

.releaserc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"branches": ["main"],
3+
"plugins": [
4+
"@semantic-release/commit-analyzer",
5+
"@semantic-release/release-notes-generator",
6+
"@semantic-release/changelog",
7+
"@semantic-release/github",
8+
["@semantic-release/git", {
9+
"assets": ["CHANGELOG.md"],
10+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
11+
}]
12+
]
13+
}

composer.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "cesnet/simplesamlphp-module-attribute_check",
3+
"description": "Module with SP files for attribute_check",
4+
"type": "simplesamlphp-module",
5+
"keywords": ["attributes", "attribute_check", "simplesamlphp"],
6+
"license": "BSD-2-Clause",
7+
"authors": [
8+
{
9+
"name": "Pavel Vyskocil",
10+
"email": "[email protected]"
11+
},
12+
{
13+
"name": "Dominik Frantisek Bucik",
14+
"email": "[email protected]"
15+
}
16+
],
17+
"require": {
18+
"simplesamlphp/simplesamlphp": "~1.17",
19+
"simplesamlphp/composer-module-installer": "~1.0"
20+
},
21+
"require-dev": {
22+
"roave/security-advisories": "dev-latest"
23+
,
24+
"symplify/easy-coding-standard": "^9.2"
25+
}
26+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$config = [
6+
'attribute_groups' => [
7+
'group_identifier1' => [
8+
'attribute_list' => ['attr1', 'attr2'],
9+
'type' => 'MANDATORY_AT_LEAST_ONE/MANDATORY_ALL/OPTIONAL',
10+
'translates' => [
11+
'title' => [
12+
'en' => 'TITLE',
13+
],
14+
'OK' => [
15+
'title' => [
16+
'en' => 'OK',
17+
],
18+
'description' => [
19+
'en' => 'OK',
20+
],
21+
],
22+
'NOT_OK' => [
23+
'title' => [
24+
'en' => 'ERROR',
25+
],
26+
'description' => [
27+
'en' => "One of 'attr1', 'attr2' must be released.",
28+
],
29+
],
30+
],
31+
],
32+
[/*...*/],
33+
],
34+
];
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"show_hide_btn": {
3+
"en": "Show / Hide all attributes",
4+
"cs": "Zobrazit / Skrýt všechny atributy"
5+
}
6+
}

ecs.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
6+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
7+
use Symplify\EasyCodingStandard\ValueObject\Option;
8+
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
9+
10+
return static function (ContainerConfigurator $containerConfigurator): void {
11+
$services = $containerConfigurator->services();
12+
$services->set(ArraySyntaxFixer::class)
13+
->call('configure', [[
14+
'syntax' => 'short',
15+
]])
16+
;
17+
18+
$parameters = $containerConfigurator->parameters();
19+
$parameters->set(Option::PATHS, [
20+
__DIR__ . '/ecs.php',
21+
__DIR__ . '/config-templates',
22+
__DIR__ . '/dictionaries',
23+
__DIR__ . '/lib',
24+
__DIR__ . '/templates',
25+
__DIR__ . '/www',
26+
__DIR__ . '/composer.json',
27+
]);
28+
29+
$containerConfigurator->import(SetList::CLEAN_CODE);
30+
$containerConfigurator->import(SetList::SYMPLIFY);
31+
$containerConfigurator->import(SetList::ARRAY);
32+
$containerConfigurator->import(SetList::COMMON);
33+
$containerConfigurator->import(SetList::COMMENTS);
34+
$containerConfigurator->import(SetList::CONTROL_STRUCTURES);
35+
$containerConfigurator->import(SetList::DOCBLOCK);
36+
$containerConfigurator->import(SetList::NAMESPACES);
37+
$containerConfigurator->import(SetList::PHPUNIT);
38+
$containerConfigurator->import(SetList::SPACES);
39+
$containerConfigurator->import(SetList::PSR_12);
40+
};

lib/AttributeCheck.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Module\attribute_check;
6+
7+
class AttributeCheck
8+
{
9+
public const MANDATORY_ONE = 'MANDATORY_AT_LEAST_ONE';
10+
11+
public const MANDATORY_ALL = 'MANDATORY_ALL';
12+
13+
public const OPTIONAL = 'OPTIONAL';
14+
15+
public const OK = 'OK';
16+
17+
public const NOT_OK = 'NOT_OK';
18+
19+
public static function handleAttributesGroup($t, $conf, $attributes): string
20+
{
21+
$translates = $conf['translates'];
22+
$type = $conf['type'];
23+
24+
if (! in_array($type, [self::MANDATORY_ONE, self::MANDATORY_ALL, self::OPTIONAL], true)) {
25+
throw new \SimpleSAML\Error\Exception('AttributeSP: Bad type!');
26+
}
27+
28+
$title = self::translate($t, $translates, 'title');
29+
$description = self::translate($t, $translates, 'description');
30+
31+
$group_attributes = $conf['attribute_list'];
32+
if (! is_array($group_attributes)) {
33+
throw new \SimpleSAML\Error\Exception('Attributes must be an array!');
34+
}
35+
36+
$result = self::getGroupResult($type, $group_attributes, $attributes);
37+
38+
$resultTitle = self::translate($t, $translates[$result], 'title');
39+
$resultDescription = self::translate($t, $translates[$result], 'description');
40+
41+
return "<div class='alert " . self::getAlertClass(
42+
$type,
43+
$result
44+
) . "'><strong>" . $title . '</strong> - ' . $resultTitle . '<br/><br/>' . $resultDescription . '</div>';
45+
}
46+
47+
private static function translate($t, $translates, $key): string
48+
{
49+
if ($translates === null) {
50+
throw new \SimpleSAML\Error\Exception('Translation configuration cannot be null!');
51+
}
52+
53+
if (isset($translates[$key])) {
54+
return $t->getTranslation($translates[$key]);
55+
}
56+
57+
return '';
58+
}
59+
60+
private static function getGroupResult($type, array $group_attributes, $attributes): string
61+
{
62+
if (in_array($type, [self::MANDATORY_ONE, self::OPTIONAL], true)) {
63+
foreach ($group_attributes as $item) {
64+
if (is_string($item)) {
65+
if (array_key_exists($item, $attributes)) {
66+
return self::OK;
67+
}
68+
} elseif (is_array($item)) {
69+
foreach ($item as $listItem) {
70+
if (! array_key_exists($item, $attributes)) {
71+
return self::NOT_OK;
72+
}
73+
}
74+
return self::OK;
75+
}
76+
}
77+
return self::NOT_OK;
78+
}
79+
foreach ($group_attributes as $item) {
80+
if (is_string($item)) {
81+
if (! array_key_exists($item, $attributes)) {
82+
return self::NOT_OK;
83+
}
84+
} elseif (is_array($item)) {
85+
foreach ($item as $listItem) {
86+
if (! array_key_exists($item, $attributes)) {
87+
return self::NOT_OK;
88+
}
89+
}
90+
}
91+
}
92+
return self::OK;
93+
}
94+
95+
private static function getAlertClass($type, $result): string
96+
{
97+
if (in_array($type, [self::MANDATORY_ONE, self::MANDATORY_ALL], true)) {
98+
if ($result === self::OK) {
99+
return 'alert-success';
100+
}
101+
return 'alert-danger';
102+
}
103+
if ($result === self::OK) {
104+
return 'alert-success';
105+
}
106+
return 'alert-warning';
107+
}
108+
}

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "simplesamlphp-module-europdx",
3+
"private": true,
4+
"devDependencies": {
5+
"@semantic-release/changelog": "^5.0.1",
6+
"@semantic-release/git": "^9.0.0",
7+
"semantic-release": "^17.4.2"
8+
}
9+
}

templates/attribute_check-tpl.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php declare(strict_types=1);
2+
3+
use SimpleSAML\Module;
4+
use SimpleSAML\Module\attribute_check\AttributeCheck;
5+
6+
/**
7+
* This is simple example of template where user has to accept usage policy
8+
*
9+
* Allow type hinting in IDE
10+
*
11+
* @var SimpleSAML\XHTML\Template $this
12+
*/
13+
$attributes = $this->data['attributes'];
14+
$attributesGroupConfiguration = $this->data['attributes_group_config'];
15+
16+
17+
$this->data['header'] = '';
18+
$this->data['head'] = '<link rel="stylesheet" media="screen" type="text/css" href="' .
19+
Module::getModuleUrl('attribute_check/res/bootstrap/css/bootstrap.css') . '" />';
20+
$this->data['head'] .= '<link rel="stylesheet" media="screen" type="text/css" href="' .
21+
Module::getModuleUrl('attribute_check/res/css/attribute_check.css') . '" />';
22+
$this->data['head'] .= '<script src="' . Module::getModuleUrl(
23+
'attribute_check/res/bootstrap/js/bootstrap.js'
24+
) . '" ></script>';
25+
26+
$this->includeAtTemplateBase('includes/header.php');
27+
28+
foreach ($attributesGroupConfiguration as $group) {
29+
echo AttributeCheck::handleAttributesGroup($this, $group, $attributes);
30+
}
31+
32+
?>
33+
<div>
34+
<button class="btn btn-primary btn-show-hide" type="button" data-bs-toggle="collapse" data-bs-target="#all_attributes" aria-expanded="false" aria-controls="all_attributes">
35+
<?php
36+
echo $this->t('{attribute_check:attribute_check:show_hide_btn}');
37+
?>
38+
</button>
39+
</div>
40+
<?php
41+
42+
echo "<div class='collapse attributes_block' id='all_attributes'>";
43+
foreach ($attributes as $attributeName => $attributeValue) {
44+
echo "<div class='row attribute_row'>";
45+
echo "<div class='col-md-4 attribute_name'>";
46+
echo '<div>' . $attributeName . '</div>';
47+
echo '</div>';
48+
49+
echo "<div class='col-md-8 attribute_value'>";
50+
if (count($attributeValue) > 1) {
51+
echo '<ul>';
52+
foreach ($attributeValue as $value) {
53+
echo '<li>' . $value . '</li>';
54+
}
55+
echo '</ul>';
56+
} elseif (count($attributeValue) === 1) {
57+
echo '<div>' . $attributeValue[0] . '</div>';
58+
} else {
59+
echo '<div></div>';
60+
}
61+
62+
echo '</div>';
63+
echo '</div>';
64+
}
65+
echo '</div>';
66+
67+
$this->includeAtTemplateBase('includes/footer.php');

0 commit comments

Comments
 (0)