Start of work to enable creation of new entries
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 28s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m30s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 9m28s
Create Docker Image / Final Docker Image Manifest (push) Successful in 9s
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 28s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m30s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 9m28s
Create Docker Image / Final Docker Image Manifest (push) Successful in 9s
This commit is contained in:
parent
f9bd352bfb
commit
6ebf588b1f
@ -145,9 +145,9 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
||||
// Attribute values
|
||||
'values' => $this->values,
|
||||
// Required by Object Classes
|
||||
'required_by' => $this->schema->required_by_object_classes,
|
||||
'required_by' => $this->schema?->required_by_object_classes ?: collect(),
|
||||
// Used in Object Classes
|
||||
'used_in' => $this->schema->used_in_object_classes,
|
||||
'used_in' => $this->schema?->used_in_object_classes ?: collect(),
|
||||
|
||||
default => throw new \Exception('Unknown key:' . $key),
|
||||
};
|
||||
|
49
app/Classes/LDAP/Attribute/RDN.php
Normal file
49
app/Classes/LDAP/Attribute/RDN.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents the RDN for an Entry
|
||||
*/
|
||||
final class RDN extends Attribute
|
||||
{
|
||||
private string $base;
|
||||
private Collection $attrs;
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
return match ($key) {
|
||||
'base' => $this->base,
|
||||
'attrs' => $this->attrs->pluck('name'),
|
||||
default => parent::__get($key),
|
||||
};
|
||||
}
|
||||
|
||||
public function hints(): array
|
||||
{
|
||||
return [
|
||||
'required' => __('RDN is required')
|
||||
];
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute.rdn')
|
||||
->with('o',$this);
|
||||
}
|
||||
|
||||
public function setAttributes(Collection $attrs): void
|
||||
{
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
public function setBase(string $base): void
|
||||
{
|
||||
$this->base = $base;
|
||||
}
|
||||
}
|
@ -208,7 +208,7 @@ final class ObjectClass extends Base
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
return match ($key) {
|
||||
'attributes' => $this->getAllAttrs(),
|
||||
'attributes' => $this->getAllAttrs(TRUE),
|
||||
'sup' => $this->sup_classes,
|
||||
'type_name' => match ($this->type) {
|
||||
Server::OC_STRUCTURAL => 'Structural',
|
||||
@ -223,13 +223,18 @@ final class ObjectClass extends Base
|
||||
/**
|
||||
* Return a list of attributes that this objectClass provides
|
||||
*
|
||||
* @param bool $parents
|
||||
* @return Collection
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function getAllAttrs(): Collection
|
||||
public function getAllAttrs(bool $parents=FALSE): Collection
|
||||
{
|
||||
return $this->getMustAttrs()
|
||||
->merge($this->getMayAttrs());
|
||||
return $this->getMustAttrs($parents)
|
||||
->transform(function($item) {
|
||||
$item->required = true;
|
||||
return $item;
|
||||
})
|
||||
->merge($this->getMayAttrs($parents));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@ namespace App\Classes\LDAP\Schema;
|
||||
final class ObjectClassAttribute extends Base {
|
||||
// This Attribute's root.
|
||||
private string $source;
|
||||
public bool $required = FALSE;
|
||||
|
||||
/**
|
||||
* Creates a new ObjectClassAttribute with specified name and source objectClass.
|
||||
@ -31,11 +32,9 @@ final class ObjectClassAttribute extends Base {
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'source':
|
||||
return $this->source;
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
return match ($key) {
|
||||
'source' => $this->source,
|
||||
default => parent::__get($key),
|
||||
};
|
||||
}
|
||||
}
|
@ -22,15 +22,15 @@ class APIController extends Controller
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
return $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
return $base
|
||||
->transform(fn($item)=>
|
||||
[
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,15 +45,22 @@ class APIController extends Controller
|
||||
|
||||
return (config('server'))
|
||||
->children($dn)
|
||||
->transform(function($item) {
|
||||
return [
|
||||
->transform(fn($item)=>
|
||||
[
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'icon'=>$item->icon(),
|
||||
'lazy'=>Arr::get($item->getAttribute('hassubordinates'),0) == 'TRUE',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
])
|
||||
->prepend(
|
||||
[
|
||||
'title'=>sprintf('[%s]',__('Create Entry')),
|
||||
'item'=>Crypt::encryptString(sprintf('*%s|%s','create_new',$dn)),
|
||||
'lazy'=>FALSE,
|
||||
'icon'=>'fas fa-fw fa-square-plus text-warning',
|
||||
'tooltip'=>__('Create new LDAP item here'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function schema_view(Request $request)
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
@ -12,16 +15,16 @@ use Illuminate\Support\Facades\Redirect;
|
||||
use LdapRecord\Exceptions\InsufficientAccessException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Query\ObjectNotFoundException;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
use App\Classes\LDAP\{Attribute,Server};
|
||||
use App\Classes\LDAP\Import\LDIF as LDIFImport;
|
||||
use App\Classes\LDAP\Export\LDIF as LDIFExport;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Http\Requests\{EntryRequest,ImportRequest};
|
||||
use App\Http\Requests\{EntryAdd,EntryRequest,ImportRequest};
|
||||
use App\Ldap\Entry;
|
||||
use App\View\Components\AttributeType;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
@ -59,13 +62,60 @@ class HomeController extends Controller
|
||||
public function dn_frame(Request $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->post('key'));
|
||||
$cmd = '';
|
||||
|
||||
$page_actions = collect(['edit'=>TRUE,'copy'=>TRUE]);
|
||||
if (str_contains($dn,'|')) {
|
||||
$m = [];
|
||||
|
||||
return view('frames.dn')
|
||||
->with('o',config('server')->fetch($dn))
|
||||
->with('dn',$dn)
|
||||
->with('page_actions',$page_actions);
|
||||
if (preg_match('/\*([a-z_]+)\|(.+)$/',$dn,$m)) {
|
||||
$cmd = $m[1];
|
||||
$dn = $m[2];
|
||||
}
|
||||
}
|
||||
|
||||
return match ($cmd) {
|
||||
'create_new' => view('frames.create')
|
||||
->with('o',config('server')->fetch($dn))
|
||||
->with('step',0)
|
||||
->with('dn',$dn),
|
||||
|
||||
default => view('frames.dn')
|
||||
->with('o',config('server')->fetch($dn))
|
||||
->with('dn',$dn)
|
||||
->with('page_actions',collect(['edit'=>TRUE,'copy'=>TRUE])),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object in the LDAP server
|
||||
*
|
||||
* @param EntryAdd $request
|
||||
* @return Factory|View|Application|object
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function entry_add(EntryAdd $request)
|
||||
{
|
||||
switch ($request->step) {
|
||||
case 1:
|
||||
$container = Crypt::decryptString($request->dn);
|
||||
|
||||
$o = new Entry;
|
||||
$o->objectclass = $request->objectclass;
|
||||
foreach($o->getAvailableAttributes()->filter(fn($item)=>$item->required) as $ao)
|
||||
$o->addAttribute($ao,['']);
|
||||
|
||||
$o->setRDNBase($container);
|
||||
|
||||
return view('frame')
|
||||
->with('subframe',$request->frame)
|
||||
->with('bases',$this->bases())
|
||||
->with('o',$o)
|
||||
->with('step',$request->step)
|
||||
->with('dn',$container);
|
||||
|
||||
default:
|
||||
throw new InvalidUsage('Invalid entry step');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,26 +309,30 @@ class HomeController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Application home page
|
||||
* This is the main page render function
|
||||
*
|
||||
* If a DN is set, when render a DN info/edit frame
|
||||
* If a frame is set, then we render that (sub)frame
|
||||
*/
|
||||
public function home()
|
||||
{
|
||||
if (old('dn'))
|
||||
if (old('frame'))
|
||||
return view('frame')
|
||||
->with('subframe',old('frame'))
|
||||
->with('bases',$this->bases())
|
||||
->with('o',old('dn') ? config('server')->fetch($dn=Crypt::decryptString(old('dn'))) : NULL)
|
||||
->with('dn',$dn ?? NULL);
|
||||
|
||||
elseif (old('dn'))
|
||||
return view('frame')
|
||||
->with('subframe','dn')
|
||||
->with('bases',$this->bases())
|
||||
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
|
||||
->with('dn',$dn);
|
||||
|
||||
elseif (old('frame'))
|
||||
return view('frame')
|
||||
->with('subframe',old('frame'))
|
||||
->with('bases',$this->bases());
|
||||
|
||||
else
|
||||
return view('home')
|
||||
->with('bases',$this->bases())
|
||||
->with('server',config('ldap.connections.default.name'));
|
||||
->with('bases',$this->bases());
|
||||
}
|
||||
|
||||
/**
|
||||
|
33
app/Http/Requests/EntryAdd.php
Normal file
33
app/Http/Requests/EntryAdd.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Rules\{DNExists,HasStructuralObjectClass};
|
||||
|
||||
class EntryAdd extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'dn' => new DNExists,
|
||||
'objectclass' => [
|
||||
'required',
|
||||
'array',
|
||||
new HasStructuralObjectClass,
|
||||
],
|
||||
'step' => 'int|min:1|max:2',
|
||||
'frame' => [
|
||||
'string',
|
||||
Rule::in(['create']),
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
@ -6,22 +6,12 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EntryRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return config('server')
|
||||
->schema('attributetypes')
|
||||
|
@ -6,12 +6,7 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ImportRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'frame' => 'required|string|in:import',
|
||||
|
@ -12,11 +12,14 @@ use App\Classes\LDAP\Attribute;
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
use App\Classes\LDAP\Export\LDIF;
|
||||
use App\Exceptions\Import\AttributeException;
|
||||
use App\Exceptions\InvalidUsage;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
private Collection $objects;
|
||||
private bool $noObjectAttributes = FALSE;
|
||||
// For new entries, this is the container that this entry will be stored in
|
||||
private string $rdnbase;
|
||||
|
||||
/* OVERRIDES */
|
||||
|
||||
@ -46,7 +49,7 @@ class Entry extends Model
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->objects
|
||||
->map(fn($item)=>$item->values->toArray())
|
||||
->map(fn($item)=>$item->values)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
@ -92,10 +95,7 @@ class Entry extends Model
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if ((! $this->objects->get($key)) && $value) {
|
||||
$o = new Attribute($key,[]);
|
||||
$o->value = $value;
|
||||
|
||||
$this->objects->put($key,$o);
|
||||
$this->objects->put($key,Factory::create($key,$value));
|
||||
|
||||
} elseif ($this->objects->get($key)) {
|
||||
$this->objects->get($key)->value = $this->attributes[$key];
|
||||
@ -265,8 +265,12 @@ class Entry extends Model
|
||||
*/
|
||||
public function getObject(string $key): Attribute|null
|
||||
{
|
||||
return $this->objects
|
||||
->get($this->normalizeAttributeKey($key));
|
||||
return match ($key) {
|
||||
'rdn' => $this->getRDNObject(),
|
||||
|
||||
default => $this->objects
|
||||
->get($this->normalizeAttributeKey($key))
|
||||
};
|
||||
}
|
||||
|
||||
public function getObjects(): Collection
|
||||
@ -289,6 +293,16 @@ class Entry extends Model
|
||||
->filter(fn($a)=>(! $this->getVisibleAttributes()->contains(fn($b)=>($a->name === $b->name))));
|
||||
}
|
||||
|
||||
private function getRDNObject(): Attribute\RDN
|
||||
{
|
||||
$o = new Attribute\RDN('dn',['']);
|
||||
// @todo for an existing object, return the base.
|
||||
$o->setBase($this->rdnbase);
|
||||
$o->setAttributes($this->getAvailableAttributes()->filter(fn($item)=>$item->required));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this list of user attributes
|
||||
*
|
||||
@ -413,4 +427,12 @@ class Entry extends Model
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setRDNBase(string $bdn): void
|
||||
{
|
||||
if ($this->exists)
|
||||
throw new InvalidUsage('Cannot set RDN base on existing entries');
|
||||
|
||||
$this->rdnbase = $bdn;
|
||||
}
|
||||
}
|
21
app/Rules/DNExists.php
Normal file
21
app/Rules/DNExists.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
class DNExists implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute,mixed $value,Closure $fail): void
|
||||
{
|
||||
if (! config('server')->fetch($x=Crypt::decryptString($value)))
|
||||
$fail(sprintf('The DN %s doesnt exist.',$x));
|
||||
}
|
||||
}
|
23
app/Rules/HasStructuralObjectClass.php
Normal file
23
app/Rules/HasStructuralObjectClass.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class HasStructuralObjectClass implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute,mixed $value,Closure $fail): void
|
||||
{
|
||||
foreach ($value as $item)
|
||||
if (config('server')->schema('objectclasses',$item)->isStructural())
|
||||
return;
|
||||
|
||||
$fail('There isnt a StructuralObject class.');
|
||||
}
|
||||
}
|
4
public/css/fixes.css
vendored
4
public/css/fixes.css
vendored
@ -304,3 +304,7 @@ div#objectClass .input-group-delete {
|
||||
right: 10px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
background-color: #fafafa;
|
||||
}
|
25
resources/views/components/attribute/rdn.blade.php
Normal file
25
resources/views/components/attribute/rdn.blade.php
Normal file
@ -0,0 +1,25 @@
|
||||
<!-- $o=RDN::class -->
|
||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
||||
@foreach($o->values as $value)
|
||||
@if($edit)
|
||||
<div class="input-group has-validation mb-3">
|
||||
<x-form.select
|
||||
name="rdn"
|
||||
:options="$o->attrs->map(fn($item)=>['id'=>$item,'value'=>$item])"
|
||||
/>
|
||||
|
||||
<span class="input-group-text">=</span>
|
||||
<input type="text" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'border-focus'=>$o->values->contains($value)]) name="rdn" placeholder="rdn">
|
||||
<label class="input-group-text" for="inputGroupSelect02">,{{ $o->base }}</label>
|
||||
|
||||
<div class="invalid-feedback pb-2">
|
||||
@if($e)
|
||||
{{ join('|',$e) }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
{{ $value }}
|
||||
@endif
|
||||
@endforeach
|
||||
</x-attribute.layout>
|
@ -51,7 +51,6 @@
|
||||
$('select#newoc').select2({
|
||||
dropdownParent: $('#new_objectclass-modal'),
|
||||
theme: 'bootstrap-5',
|
||||
allowClear: true,
|
||||
multiple: true,
|
||||
data: data,
|
||||
});
|
||||
|
@ -54,10 +54,16 @@
|
||||
width: 'style',
|
||||
allowClear: {{ $allowclear ?? 'false' }},
|
||||
placeholder: '{{ $placeholder ?? '' }}',
|
||||
multiple: {{ $multiple ?? 'false' }},
|
||||
@isset($addvalues)
|
||||
tags: true,
|
||||
@endisset
|
||||
});
|
||||
|
||||
@if(isset($multiple) && (! $multiple))
|
||||
$('#{{ $id ?? $name }}').val(' ');
|
||||
$('#{{ $id ?? $name }}').trigger('change');
|
||||
@endif
|
||||
});
|
||||
</script>
|
||||
@append
|
155
resources/views/frames/create.blade.php
Normal file
155
resources/views/frames/create.blade.php
Normal file
@ -0,0 +1,155 @@
|
||||
@extends('layouts.dn')
|
||||
|
||||
@section('page_title')
|
||||
@include('fragment.dn.header')
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
<div class="row">
|
||||
<p class="alert alert-danger text-center">
|
||||
This is a tech preview of what is to come, and it is by no means complete.
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-1 col-10">
|
||||
<div class="main-card mb-3 card">
|
||||
<form id="create-form" action="{{ url('entry/add') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<input type="hidden" name="frame" value="create">
|
||||
<input type="hidden" name="dn" value="{{ Crypt::encryptString($dn) }}">
|
||||
<input type="hidden" name="step" value="{{ ++$step }}">
|
||||
|
||||
<div class="card-header">
|
||||
@lang('Create New Entry')
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
@switch($step)
|
||||
@case(1)
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<x-form.select
|
||||
id="objectclass"
|
||||
name="objectclass[]"
|
||||
:label="__('Select a Structural ObjectClass...')"
|
||||
:options="($oc=config('server')->schema('objectclasses'))
|
||||
->filter(fn($item)=>$item->isStructural())
|
||||
->sortBy(fn($item)=>$item->name_lc)
|
||||
->map(fn($item,$key)=>['id'=>$key,'value'=>$item->name])"
|
||||
multiple="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@case(2)
|
||||
<x-attribute-type :edit="true" :o="$o->getObject('rdn')"/>
|
||||
|
||||
@foreach ($o->getVisibleAttributes() as $ao)
|
||||
<x-attribute-type :edit="true" :o="$ao"/>
|
||||
@endforeach
|
||||
|
||||
<div id="newattrs"></div>
|
||||
|
||||
<!-- Add new attributes -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-1 col-md-2"></div>
|
||||
<div class="col-12 col-sm-10 col-md-8">
|
||||
<div class="d-none" id="newattr-select">
|
||||
|
||||
@if($o->getMissingAttributes()->count())
|
||||
<div class="row">
|
||||
<div class="col-12 bg-dark text-light p-2">
|
||||
<i class="fas fa-plus-circle"></i> Add New Attribute
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 pt-2">
|
||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name_lc])"/>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
@break;
|
||||
@endswitch
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<span class="ms-auto">
|
||||
<x-form.submit action="Next" form="dn-add"/>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
var dn = '{{ $o->getDNSecure() }}';
|
||||
var oc = {!! $o->getObject('objectclass')->values !!};
|
||||
|
||||
function editmode() {
|
||||
$('#dn-edit input[name="dn"]').val(dn);
|
||||
|
||||
$('button[id=entry-edit]').addClass('active').removeClass('btn-outline-dark').addClass('btn-outline-light');
|
||||
|
||||
// Find all input items and turn off readonly
|
||||
$('input.form-control').each(function() {
|
||||
// Except for objectClass - @todo show an "X" instead
|
||||
if ($(this)[0].name.match(/^objectclass/))
|
||||
return;
|
||||
|
||||
$(this).attr('readonly',false);
|
||||
});
|
||||
|
||||
// Our password type
|
||||
$('div#userPassword .form-select').each(function() {
|
||||
$(this).prop('disabled',false);
|
||||
})
|
||||
|
||||
$('.row.d-none').removeClass('d-none');
|
||||
$('.addable.d-none').removeClass('d-none');
|
||||
$('.deletable.d-none').removeClass('d-none');
|
||||
|
||||
@if($o->getMissingAttributes()->count())
|
||||
$('#newattr-select.d-none').removeClass('d-none');
|
||||
@endif
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#newattr').on('change',function(item) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
beforeSend: function() {},
|
||||
success: function(data) {
|
||||
$('#newattrs').append(data);
|
||||
},
|
||||
error: function(e) {
|
||||
if (e.status != 412)
|
||||
alert('That didnt work? Please try again....');
|
||||
},
|
||||
url: '{{ url('entry/attr/add') }}/'+item.target.value,
|
||||
data: {
|
||||
objectclasses: oc,
|
||||
},
|
||||
cache: false
|
||||
});
|
||||
|
||||
// Remove the option from the list
|
||||
$(this).find('[value="'+item.target.value+'"]').remove()
|
||||
|
||||
// If there are no more options
|
||||
if ($(this).find("option").length === 1)
|
||||
$('#newattr-select').remove();
|
||||
});
|
||||
|
||||
editmode();
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -38,6 +38,7 @@ Route::group(['prefix'=>'user'],function() {
|
||||
Route::get('image',[HomeController::class,'user_image']);
|
||||
});
|
||||
|
||||
Route::post('entry/add',[HomeController::class,'entry_add']);
|
||||
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
|
||||
Route::post('entry/password/check/',[HomeController::class,'entry_password_check']);
|
||||
Route::post('entry/attr/add/{id}',[HomeController::class,'entry_attr_add']);
|
||||
|
Loading…
x
Reference in New Issue
Block a user