Added registrar create form

This commit is contained in:
Pinga 2023-11-14 17:17:21 +02:00
parent e08ebcdbce
commit d0f1a92a6d
7 changed files with 577 additions and 8 deletions

View file

@ -6,6 +6,7 @@ use App\Models\RegistryTransaction;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Container\ContainerInterface;
use League\ISO3166\ISO3166;
class RegistrarsController extends Controller
{
@ -13,4 +14,19 @@ class RegistrarsController extends Controller
{
return view($response,'admin/registrars/index.twig');
}
public function create(Request $request, Response $response)
{
if ($_SESSION["auth_roles"] != 0) {
return $response->withHeader('Location', '/dashboard')->withStatus(302);
}
$iso3166 = new ISO3166();
$countries = $iso3166->all();
// Default view for GET requests or if POST data is not set
return view($response,'admin/registrars/create.twig', [
'countries' => $countries,
]);
}
}

View file

@ -0,0 +1,552 @@
{% extends "layouts/app.twig" %}
{% block title %}{{ __('Create Registrar') }}{% endblock %}
{% block content %}
<div class="page-wrapper">
<!-- Page header -->
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<!-- Page pre-title -->
<div class="page-pretitle">
{{ __('Overview') }}
</div>
<h2 class="page-title">
{{ __('Create Registrar') }}
</h2>
</div>
<!-- Page title actions -->
<div class="col-auto ms-auto d-print-none">
<div class="btn-list">
<a href="#" class="btn btn-primary d-none d-sm-inline-block">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>
Create Registrar
</a>
<a href="#" class="btn btn-primary d-sm-none btn-icon" aria-label="Create Registrar">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Page body -->
<div class="page-body">
<div class="container-xl">
<div class="col-12">
<!-- Registrar Details Card -->
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">Registrar Details</h5>
<form>
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="name" class="form-label required">Name</label>
<input type="text" class="form-control" id="name" name="name">
<small class="text-muted">The official name of the registrar.</small>
</div>
<div class="mb-3">
<label for="ianaId" class="form-label">IANA ID <small class="text-muted">(International Assigned Numbers Authority ID)</small></label>
<input type="number" class="form-control" id="ianaId" name="ianaId">
<small class="text-muted">Unique identifier assigned by IANA.</small>
</div>
<div class="mb-3">
<label for="clid" class="form-label required">CLID <small class="text-muted">(Client Identifier)</small></label>
<input type="text" class="form-control" id="clid" name="clid">
<small class="text-muted">Unique client identifier for the registrar.</small>
</div>
<div class="mb-3">
<label for="prefix" class="form-label required">Prefix</label>
<input type="text" class="form-control" id="prefix" name="prefix">
<small class="text-muted">Short prefix code representing the registrar.</small>
</div>
<div class="mb-3">
<label for="email" class="form-label required">Email</label>
<input type="email" class="form-control" id="email" name="email">
<small class="text-muted">Primary contact email of the registrar.</small>
</div>
</div>
<!-- Second Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="whoisServer" class="form-label required">WHOIS Server</label>
<input type="text" class="form-control" id="whoisServer" name="whoisServer">
<small class="text-muted">Address of the registrar's WHOIS server.</small>
</div>
<div class="mb-3">
<label for="rdapServer" class="form-label required">RDAP Server</label>
<input type="text" class="form-control" id="rdapServer" name="rdapServer">
<small class="text-muted">Address of the registrar's RDAP server.</small>
</div>
<div class="mb-3">
<label for="url" class="form-label required">URL</label>
<input type="url" class="form-control" id="url" name="url">
<small class="text-muted">Registrar's official website URL.</small>
</div>
<div class="mb-3">
<label for="abuseEmail" class="form-label required">Abuse Email</label>
<input type="email" class="form-control" id="abuseEmail" name="abuseEmail">
<small class="text-muted">Email address for reporting abuse.</small>
</div>
<div class="mb-3">
<label for="abusePhone" class="form-label required">Abuse Phone</label>
<input type="tel" class="form-control" id="abusePhone" name="abusePhone">
<small class="text-muted">Phone number for reporting abuse.</small>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- Financial Information Card -->
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">Financial Information</h5>
<form>
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="accountBalance" class="form-label required">Account Balance</label>
<input type="text" class="form-control" id="accountBalance" name="accountBalance">
<small class="text-muted">Current balance in the registrar's account.</small>
</div>
<div class="mb-3">
<label for="creditLimit" class="form-label required">Credit Limit</label>
<input type="text" class="form-control" id="creditLimit" name="creditLimit">
<small class="text-muted">Maximum credit limit for the registrar.</small>
</div>
</div>
<!-- Second Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="creditThreshold" class="form-label required">Credit Threshold</label>
<input type="text" class="form-control" id="creditThreshold" name="creditThreshold">
<small class="text-muted">Credit threshold triggering alerts or actions.</small>
</div>
<div class="mb-3">
<label for="thresholdType" class="form-label required">Threshold Type</label>
<select class="form-select" id="thresholdType" name="thresholdType">
<option value="fixed">Fixed</option>
<option value="percent">Percent</option>
</select>
<small class="text-muted">Type of threshold: fixed value or percentage.</small>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- Registrar Contacts Section with Tabs -->
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">Registrar Contacts</h5>
<ul class="nav nav-tabs nav-fill" id="contactTabs" role="tablist">
<!-- Tab Headers -->
<li class="nav-item" role="presentation">
<button class="nav-link active" id="owner-tab" data-bs-toggle="tab" data-bs-target="#owner" type="button" role="tab" aria-controls="owner" aria-selected="true">Owner</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="billing-tab" data-bs-toggle="tab" data-bs-target="#billing" type="button" role="tab" aria-controls="billing" aria-selected="false">Billing</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="abuse-tab" data-bs-toggle="tab" data-bs-target="#abuse" type="button" role="tab" aria-controls="abuse" aria-selected="false">Abuse</button>
</li>
</ul>
<div class="tab-content" id="contactTabsContent">
<!-- Owner Tab -->
<div class="tab-pane fade show active" id="owner" role="tabpanel" aria-labelledby="owner-tab">
<form class="mt-3">
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" value="" id="copyOwnerData">
<label class="form-check-label" for="copyOwnerData">
Copy data to other contacts
</label>
</div>
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="ownerFirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="ownerFirstName" name="owner[first_name]" required>
</div>
<div class="mb-3">
<label for="ownerLastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="ownerLastName" name="owner[last_name]" required>
</div>
<div class="mb-3">
<label for="ownerOrg" class="form-label">Organization</label>
<input type="text" class="form-control" id="ownerOrg" name="owner[org]">
</div>
<div class="mb-3">
<label for="ownerStreet1" class="form-label">Street Addres</label>
<input type="text" class="form-control" id="ownerStreet1" name="owner[street1]">
</div>
<div class="mb-3">
<label for="ownerCity" class="form-label">City</label>
<input type="text" class="form-control" id="ownerCity" name="owner[city]" required>
</div>
</div>
<!-- Second Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="ownerSp" class="form-label">State/Province</label>
<input type="text" class="form-control" id="ownerSp" name="owner[sp]">
</div>
<div class="mb-3">
<label for="ownerPc" class="form-label">Postal Code</label>
<input type="text" class="form-control" id="ownerPc" name="owner[pc]">
</div>
<div class="mb-3">
<label for="ownerCc" class="form-label">Country</label>
<select class="form-select" id="ownerCc" name="owner[cc]" required="required">
{% for country in countries %}
<option value="{{ country.alpha2|lower }}">{{ country.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="ownerVoice" class="form-label">Phone</label>
<input type="tel" class="form-control" id="ownerVoice" name="owner[voice]">
</div>
<div class="mb-3">
<label for="ownerEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="ownerEmail" name="owner[email]" required>
</div>
</div>
</div>
</form>
</div>
<!-- Billing Tab -->
<div class="tab-pane fade" id="billing" role="tabpanel" aria-labelledby="billing-tab">
<form class="mt-3">
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="billingFirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="billingFirstName" name="billing[first_name]" required>
</div>
<div class="mb-3">
<label for="billingLastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="billingLastName" name="billing[last_name]" required>
</div>
<div class="mb-3">
<label for="billingOrg" class="form-label">Organization</label>
<input type="text" class="form-control" id="billingOrg" name="billing[org]">
</div>
<div class="mb-3">
<label for="billingStreet1" class="form-label">Street Address</label>
<input type="text" class="form-control" id="billingStreet1" name="billing[street1]">
</div>
<div class="mb-3">
<label for="billingCity" class="form-label">City</label>
<input type="text" class="form-control" id="billingCity" name="billing[city]" required>
</div>
</div>
<!-- Second Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="billingSp" class="form-label">State/Province</label>
<input type="text" class="form-control" id="billingSp" name="billing[sp]">
</div>
<div class="mb-3">
<label for="billingPc" class="form-label">Postal Code</label>
<input type="text" class="form-control" id="billingPc" name="billing[pc]">
</div>
<div class="mb-3">
<label for="billingCc" class="form-label">Country</label>
<select class="form-select" id="billingCc" name="billing[cc]" required="required">
{% for country in countries %}
<option value="{{ country.alpha2|lower }}">{{ country.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="billingVoice" class="form-label">Phone</label>
<input type="tel" class="form-control" id="billingVoice" name="billing[voice]">
</div>
<div class="mb-3">
<label for="billingEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="billingEmail" name="billing[email]" required>
</div>
</div>
</div>
</form>
</div>
<!-- Abuse Tab -->
<div class="tab-pane fade" id="abuse" role="tabpanel" aria-labelledby="abuse-tab">
<form class="mt-3">
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="abuseFirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="abuseFirstName" name="abuse[first_name]" required>
</div>
<div class="mb-3">
<label for="abuseLastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="abuseLastName" name="abuse[last_name]" required>
</div>
<div class="mb-3">
<label for="abuseOrg" class="form-label">Organization</label>
<input type="text" class="form-control" id="abuseOrg" name="abuse[org]">
</div>
<div class="mb-3">
<label for="abuseStreet1" class="form-label">Street Address</label>
<input type="text" class="form-control" id="abuseStreet1" name="abuse[street1]">
</div>
<div class="mb-3">
<label for="abuseCity" class="form-label">City</label>
<input type="text" class="form-control" id="abuseCity" name="abuse[city]" required>
</div>
</div>
<!-- Second Column -->
<div class="col-md-6">
<div class="mb-3">
<label for="abuseSp" class="form-label">State/Province</label>
<input type="text" class="form-control" id="abuseSp" name="abuse[sp]">
</div>
<div class="mb-3">
<label for="abusePc" class="form-label">Postal Code</label>
<input type="text" class="form-control" id="abusePc" name="abuse[pc]">
</div>
<div class="mb-3">
<label for="abuseCc" class="form-label">Country</label>
<select class="form-select" id="abuseCc" name="abuse[cc]" required="required">
{% for country in countries %}
<option value="{{ country.alpha2|lower }}">{{ country.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="abuseVoice" class="form-label">Phone</label>
<input type="tel" class="form-control" id="abuseVoice" name="abuse[voice]">
</div>
<div class="mb-3">
<label for="abuseEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="abuseEmail" name="abuse[email]" required>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<!-- IP Whitelisting Column -->
<div class="col-md-6">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">IP Whitelisting</h5>
<p class="card-text">
Whitelist IP addresses for secure access. Up to 5 IP addresses (IPv4 or IPv6) can be added.
</p>
<form id="ipWhitelistForm">
<div id="ipAddressFields">
<div class="mb-3 d-flex align-items-center">
<input type="text" class="form-control" name="ipAddress[]">
<button type="button" class="btn btn-primary ms-2 add-ip">+</button>
</div>
</div>
</form>
</div>
</div>
</div>
<!-- Registrar User Column -->
<div class="col-md-6">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">Registrar User</h5>
<p class="card-text">
Create a registrar user by specifying the username, email, and passwords for both EPP and panel access.
</p>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">Username</th>
<th scope="col">Email</th>
<th scope="col">EPP User Password</th>
<th scope="col">Panel User Password</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" class="form-control form-control-sm" name="user_name" placeholder="user1">
</td>
<td>
<input type="email" class="form-control form-control-sm" name="user_email" placeholder="user1@example.com">
</td>
<td>
<input type="password" class="form-control form-control-sm" name="eppPassword">
</td>
<td>
<input type="password" class="form-control form-control-sm" name="panelPassword">
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- OTE Section -->
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">Operational Test and Evaluation (OTE)</h5>
<p class="card-text">
Operational Test and Evaluation (OTE) assesses the functionality of EPP commands in a simulated environment, ensuring effective communication between the registrar's system and the registry. Below are key EPP commands and their test statuses:
</p>
<div class="row">
<!-- First Column -->
<div class="col-md-6">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center">
contact:create
<span class="badge bg-green text-green-fg">Success</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
domain:check
<span class="badge bg-orange text-orange-fg">Pending</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
domain:info
<span class="badge bg-red text-red-fg">Failed</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
domain:renew
<span class="badge bg-green text-green-fg">Success</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
domain:transfer
<span class="badge bg-orange text-orange-fg">Pending</span>
</li>
</ul>
</div>
<!-- Second Column -->
<div class="col-md-6">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center">
host:create
<span class="badge bg-green text-green-fg">Success</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
host:info
<span class="badge bg-red text-red-fg">Failed</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
contact:update
<span class="badge bg-orange text-orange-fg">Pending</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
domain:delete
<span class="badge bg-green text-green-fg">Success</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
poll:request
<span class="badge bg-orange text-orange-fg">Pending</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="footer footer-transparent d-print-none">
<div class="container-xl">
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item">
Copyright &copy; 2023
<a href="https://namingo.org" target="_blank" class="link-secondary">Namingo</a>.
</li>
</ul>
</div>
</div>
</div>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const ipForm = document.getElementById('ipWhitelistForm');
const maxFields = 5;
ipForm.addEventListener('click', function(e) {
const target = e.target;
// Handle Add IP Button Click
if (target.classList.contains('add-ip')) {
const totalFields = ipForm.querySelectorAll('input[name="ipAddress[]"]').length;
if (totalFields < maxFields) {
const newField = target.parentElement.cloneNode(true);
newField.querySelector('input').value = '';
newField.querySelector('.add-ip').classList.replace('btn-primary', 'btn-danger');
newField.querySelector('.add-ip').textContent = '-';
newField.querySelector('.add-ip').classList.replace('add-ip', 'remove-ip');
ipForm.querySelector('#ipAddressFields').appendChild(newField);
}
}
// Handle Remove IP Button Click
if (target.classList.contains('remove-ip')) {
target.parentElement.remove();
}
});
const copyCheckbox = document.getElementById('copyOwnerData');
// Function to copy data to another tab
function copyDataToTab(tabId) {
const ownerInputs = document.querySelectorAll('#owner input:not([type="checkbox"]), #owner select');
const targetFields = document.querySelectorAll(`${tabId} input:not([type='checkbox']), ${tabId} select`);
ownerInputs.forEach((input, index) => {
if (targetFields[index] && input.tagName === targetFields[index].tagName) {
targetFields[index].value = input.value;
}
});
}
copyCheckbox.addEventListener('change', function() {
if (this.checked) {
copyDataToTab('#billing');
copyDataToTab('#abuse');
} else {
// Clear fields when unchecked, if desired
['#billing', '#abuse'].forEach(tabId => {
const fields = document.querySelectorAll(`${tabId} input:not([type='checkbox']), ${tabId} select`);
fields.forEach(field => {
field.value = '';
});
});
}
});
});
</script>
{% endblock %}

View file

@ -20,11 +20,11 @@
<!-- Page title actions -->
<div class="col-auto ms-auto d-print-none">
<div class="btn-list">
<a href="#" class="btn btn-primary d-none d-sm-inline-block">
<a href="{{route('registrarcreate')}}" class="btn btn-primary d-none d-sm-inline-block">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>
Create Registrar
</a>
<a href="#" class="btn btn-primary d-sm-none btn-icon" aria-label="Create Registrar">
<a href="{{route('registrarcreate')}}" class="btn btn-primary d-sm-none btn-icon" aria-label="Create Registrar">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>
</a>
</div>

View file

@ -148,7 +148,7 @@
</a>
</div>
</li>
<li {{ is_current_url('registrars') or is_current_url('users') ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
<li {{ is_current_url('registrars') or is_current_url('users') or is_current_url('registrarcreate') ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-expanded="false">
<span class="nav-link-icon d-md-none d-lg-inline-block"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 13a3 3 0 1 0 0 -6a3 3 0 0 0 0 6z"></path><path d="M12 3c7.2 0 9 1.8 9 9s-1.8 9 -9 9s-9 -1.8 -9 -9s1.8 -9 9 -9z"></path><path d="M6 20.05v-.05a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v.05"></path></svg>
</span>
@ -160,7 +160,7 @@
<a class="dropdown-item" href="{{route('registrars')}}">
{{ __('List Registrars') }}
</a>
<a class="dropdown-item" href="#">
<a class="dropdown-item" href="{{route('registrarcreate')}}">
{{ __('Create Registrar') }}
</a>
<div class="dropdown-divider"></div>

View file

@ -55,6 +55,7 @@ $app->group('', function ($route) {
$route->get('/host/{domain}', HostsController::class . ':viewHost')->setName('viewHost');
$route->get('/registrars', RegistrarsController::class .':view')->setName('registrars');
$route->map(['GET', 'POST'], '/registrar/create', RegistrarsController::class . ':create')->setName('registrarcreate');
$route->get('/users', UsersController::class .':view')->setName('users');

View file

@ -100,9 +100,9 @@ CREATE TABLE IF NOT EXISTS `registry`.`registrar_contact` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`registrar_id` int(10) unsigned NOT NULL,
`type` enum('owner','admin','billing','tech','abuse') NOT NULL default 'admin',
`title` varchar(255) NOT NULL,
`title` varchar(255) default NULL,
`first_name` varchar(255) NOT NULL,
`middle_name` varchar(255) NOT NULL,
`middle_name` varchar(255) default NULL,
`last_name` varchar(255) NOT NULL,
`org` varchar(255) default NULL,
`street1` varchar(255) default NULL,

View file

@ -109,9 +109,9 @@ CREATE TABLE registry.registrar_contact (
"id" serial8,
"registrar_id" int CHECK ("registrar_id" >= 0) NOT NULL,
"type" varchar CHECK ("type" IN ( 'owner','admin','billing','tech','abuse' )) NOT NULL default 'admin',
"title" varchar(255) NOT NULL,
"title" varchar(255) default NULL,
"first_name" varchar(255) NOT NULL,
"middle_name" varchar(255) NOT NULL,
"middle_name" varchar(255) default NULL,
"last_name" varchar(255) NOT NULL,
"org" varchar(255) default NULL,
"street1" varchar(255) default NULL,