Code Monkey home page Code Monkey logo

socrates's People

Contributors

alexolival avatar allcontributors[bot] avatar flavioheleno avatar joaofscruz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

socrates's Issues

[v1.3.0] Implement Mexico 🇲🇽

This is a pilot task for the upcoming release: v1.3.0 - The New World.

You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point of view but needs to be backed up with an investigation about the national identifier.

As a rough guide:

  • Write tests (feel free to copy the existing ones and modify them)
  • Add the country's ISO code in the proper array (validator or extractor) in the src/Config/Countries.php file
  • Create a directory with the name of the country under the Core directory
  • Implement either or both the IdValidator or CitizenInformationExtractor interface
  • And WRITE TESTS!

[v2.0.0] Remove Carbon dependency

As I'm working on the JS/TS/npm port, I'm striving to keep dependencies to a minimum - something that the npm ecosystem is plagued with.

However we ourselves are forcing a dependency on a DateTime wrapper library that, no matter how great it is, not all projects will use.
PHP's DateTime class is fine and we should refactor our date handling to it, including Citizen's return type.

Implement Germany 🇩🇪

No solid leads or good official information was found on how to validate the German Personal Identification Number.

Help is needed to implement it, if possible.

[v1.3.0] Improve contribution guidelines

As this repository gets more attention and more people want to contribute, it's more important to make sure we have a robust document explaining what our standards of quality and code style are.

The CONTRIBUTING.md file should have examples on how to properly implement a country, put a PR up and what tools can be used to help verify the code before pushing to the repository.

Implement Austria 🇦🇹

No solid leads or good official information was found on how to validate the Austrian Personal Identification Number.

Help is needed to implement it, if possible.

Add Facade method annotations

Using the Socrates Facade is extremely convenient; however it does not support autocompletion due to its "static proxy" nature.

We should add method annotations to the Facade to allow IDE autocompletion and provide a better Developer Experience.

[v1.3.0] Improve PHPDoc on InvalidLengthException

InvalidLengthException is a good example of am internal exception with a nice DX for people contributing to the codebase.
Clearly, our recent contributors know how to use it:

throw new InvalidLengthException('Peru CUI', '9', $idLength);

We can go a bit further though and document the constructor with each parameter being described in the constructor, rather than what we have now:

/**
* Create a new InvalidLengthException instance.
*
* @param string $designation
* @param string $requiredCharacters
* @param string $givenCharacters
* @return void
*/

Additionally, we don't need a $designation field in the class, as it is not being used anywhere else.

[v1.3.0] Remove Laravel framework detection

These lines of code are a hacky way of detecting if we are pulled in a Laravel project for the purpose of detecting the locale using the framework's App::getLocale() method:

$runningLaravel = class_exists(\Illuminate\Support\Facades\App::class);
if (! $runningLaravel && $countryCode === '') {
throw new InvalidCountryCodeException('No country code provided.');
}
if ($runningLaravel && $countryCode === '') {
$countryCode = \Illuminate\Support\Facades\App::getLocale();
}
$countryCodeLength = strlen($countryCode);
if ($countryCodeLength !== 2 && $countryCodeLength !== 5) {
throw new InvalidCountryCodeException("The code '$countryCode' is not in ISO 3166-2 format.");
}
if ($countryCodeLength === 5) {
$countryCode = substr($countryCode, -2);
}

The idea was to have a default behaviour in which we would assume that if no country code was passed, then the user was referencing whatever country corresponds to the application's locale (see #84)
However, as mentioned above, not only this is hacky but sort of gimmicky. There's no use for this, so let's remove it.

Fix & standardize Validation tests across all countries

This problem was found thanks to #57:

public function test_validation_behaviour(): void
{
    foreach ($this->validIds as $id) {
        $this->assertTrue(
            Socrates::validateId($id, 'PT')
        );
    }
    
    // Here be dragons...
    $this->expectException(InvalidLengthException::class);

    Socrates::validateId('11084129 8 ZX', 'PT');

    // Everything here passes...
    $this->assertFalse(
        Socrates::validateId('14897475 4 ZY5', 'PT')
    );
}

Not only some countries test for a single invalid ID - which isn't ideal - but even those that test with multiple of those have that same problem.

The correct order of assertions should be:

public function test_validation_behaviour(): void
{
    foreach ($this->validIds as $id) {
        $this->assertTrue(
            Socrates::validateId($id, 'PT')
        );
    }

    foreach ($this->invalidIds as $invalidId) {
        $this->assertFalse(
            Socrates::validateId($invalidId, 'PT')
        );
    }

    $this->expectException(InvalidLengthException::class);

    Socrates::validateId('11084129 8 ZX', 'PT');
}

So we need to ahead and fix these tests for all countries.

Implement Luxembourg 🇱🇺

No solid leads or good official information was found on how to validate the Luxembourger Personal Identification Number.

Help is needed to implement it, if possible.

Implement USA 🇺🇸

This is a pilot task for the upcoming release (surprise surprise 🎉 North America is the next addition)..

You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point fo view, but needs to be backed up with an investigation about the national identifier.

As a rough guide:

  • Write tests (feel free to copy the existing ones and modify them)
  • Add the country's ISO code in the proper array (validator or extractor) in the src/Config/Countries.php file
  • Create a directory with the name of the country under the Core directory
  • Implement either or both the IdValidator or CitizenInformationExtractor interface
  • And WRITE TESTS!

Fix the COUNTRIES.md table

There are duplicated cells, as well as erroneous information about which countries support extraction.

Let's fix the table, and move it to the project root for easy access (for lazy people who skim through the docs).

Luxembourg ID validation

According to this documentation and this wikipedia page, the Luxembourg ID validation is performed by:

  1. computing check digit, based on the Luhn Algorithm and the first 11 digits of the ID, and compare it with the 12nd digit of the ID.
  2. computing check digit, based on the Verhoeff Algorithm and the first 11 digits of the ID, and compare it with the 13rd digit of the ID.

This is not what is happening in:

return $this->checkLuhn($ninArray) && $this->checkVerhoeff($ninArray);

I've been trying to get some real ID's to test it, but I wasn't successful.

Can you check?

Reference the official country documentation

The algorithms from this library are specified by national authorities of each country.
For example, for Portugal, one can find the official documents in the Portuguese government official website.

You should add a link to the official document (and the date) you based your calculation on, either in the respective country file or somewhere in the documentation. I think this will be very helpful when using the library, either to identify possible bugs or to simply have additional documentation to check for a particular country.

List of documentation links:

Fix the request Validator

The request validator is currently implemented like so:

// socrates/src/Laravel/SocratesServiceProvider.php
Validator::extend('national_id', function ($attribute, $value, $parameters, $validator) {
    $countryCode = strtoupper($parameters[0]);

    if (! in_array($countryCode, Countries::$all, true)) {
        return false;
    }

    try {
        return app('socrates')->validateId($value, $countryCode);
    } catch (\Exception $e) {
        return false;
    }
}, 'National ID number is invalid.');

This however silences the exception, and doesn't let the framework gracefully handle a ValidationException like it should.

Standardise Exceptions

Most Exceptions in the codebase are very similar and use the same format or messages.
For the sake of simplicity and future maintainability, we should standardise them.

Implement Cyprus 🇨🇾

No solid leads or good official information was found on how to validate the Cypriot Personal Identification Number.

Help is needed to implement it, if possible.

Prepare the README.md

Sections which we could/should have:

  • Logo
  • General description & information (countries we don't support and why, how countries differ on the definition of "ID", etc.)
  • Installation
  • How to use
  • Use case examples (preferably with screenshots)
  • Contributing

[v1.3.0] Incorrect ID validation for Belgium.

Related to #75, I see some problems with the current implementation:

  • It does not allow 00 as day or 00 as month while the docs specify that it is allowed for people whose day/month of birth was unknown at the time of registration.
  • Digits 7-9 represent a sequence number that ranges from 001 to 998 (both inclusive) so values 000 and 999 are invalid. The current implementation does not seem to check this.

See https://github.com/reducktion/socrates-java/pull/36/files for an implementation in the Java fork that does take these things into account.

I'm up for fixing it if you want, please confirm.

Implement Canada 🇨🇦

This is a pilot task for the upcoming release (surprise surprise 🎉 North America is the next addition).

You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point fo view, but needs to be backed up with an investigation about the national identifier.

As a rough guide:

  • Write tests (feel free to copy the existing ones and modify them)
  • Add the country's ISO code in the proper array (validator or extractor) in the src/Config/Countries.php file
  • Create a directory with the name of the country under the Core directory
  • Implement either or both the IdValidator or CitizenInformationExtractor interface
  • And WRITE TESTS!

Countries Implementation

Let's make a list of the countries to be implemented:

  •  Albania
    Austria
    Belarus
  •  Belgium
  •  Bosnia and Herzegovina
  •  Bulgaria
  •  Croatia
    Cyprus
  •  Czech Republic
  •  Denmark
  •  Estonia
  •  Finland
  •  France
    Germany
  •  Greece
  •  Hungary
  •  Iceland
  •  Ireland
  •  Italy
  •  Kosovo
  •  Latvia
  •  Lithuania
  •  Luxembourg
  •  Moldova
  •  Montenegro
  •  Netherlands
  •  North Macedonia
  •  Norway
  •  Poland
  •  Portugal
  • Romania
  • Serbia
  • Slovakia
  •  Slovenia
  •  Spain
  •  Sweden
  • Turkey
  •  Ukraine
  •  United Kingdom
  •  Switzerland

French special month codes

Following this reference documentation (cited in wikipedia) there is the possibility of special digits for the month section of the french national identity card number:

6.3 3 ème composante : mois de naissance (2 chiffres)
codification : de 01 (janvier) à 12 (décembre)
Les mois de naissance fictifs 20 à 30 ou 50 ou plus caractérisent le NIR d'une personne inscrite aurépertoire sur la base d'une pièce d'état civil ne mentionnant pas son mois de naissance (cf.précisions complémentaires).Les mois de naissance "pseudo-fictifs" 31 (janvier) à 42 (décembre) caractérisent le NIR d'unepersonne inscrite au répertoire sur la base d'une pièce d'état civil incomplète mais mentionnanttoutefois un mis de naissance.
from Normalisation du numéro INSEEdes personnes physiques

Which means (if google translate does not fail me) that the following options are available:

  • 01 - 12: Representing the month of the year
  • 20 - 30, 50: Indicating that the month of birth is unknown
  • 31 - 42: The person has an incomplete civil status document, but their month of birth is known

It seems to me that the current code will fail with any of the special digits:

private function getDateOfBirth(string $id): Carbon
{
  $dateDigits = substr($id, 1, 4);
  [$year, $month] = str_split($dateDigits, 2);
  $currentYear = (int) now()->format('y');

  $year = (int) $year > $currentYear ? (int) $year + 1900 : (int) $year + 2000;

  return Carbon::createFromFormat('Y-m', "$year-$month");
}

The extraction should have the month of birth information, even with the 31-42 digits, and ideally not fail (rather be incomplete) on the 20-30 or 50 digits.

[v1.3.0] Deprecate Carbon instance returning methods

We have decided to step away from having Carbon as a dependency in favor of returning native PHP DateTime objects.
Changing the methods immediately would be a breaking change, so we have decided to deprecate the existing ones instead and have both options available. Later in another major release the old methods may be removed.

  • Deprecate Carbon returning public API methods
  • Implement new {oldMethodName}Native() methods returning a DateTime
  • Update tests to use native DateTime assertions
  • Update documentation to reflect these changes

Related to #86

[v1.3.0] Create country constants

As one can see in the Java port, it's much better to provide the user with whatever countries are supported rather than have them guess or research what countries can be used:

socrates.validateId('abcd', Country.PT);

As proud as I am of our exception handling for this case, we should create constants for each country and remove it.

e.g.:

$socrates->validateId('xpto', Country::PT);

or

$socrates->validateId('xpto', Country::PORTUGAL);

France Metropolitan Lyon Region Validation

On the region digits, there is at least one case Metropolitan Lyon which has a letter in the COG.

'69M' => 'Metropolitan Lyon',

But the validation algorithm for France will throw a cast error when trying to parse an id that includes that COG.

public function validate(string $id): bool
{
  $id = $this->sanitize($id);

  $checksum = (int) substr($id, -2);
  $id = substr($id, 0, -2);

  $result = 97 - ((int) $id % 97); // cast error for an id like 1510269M02043

  return $checksum === $result;
}

I can't find any documentation on how to perform the control digit calculation for a scenario like that though.

Implement Belarus 🇧🇾

No solid leads or good official information was found on how to validate the Belarusian Personal Identification Number.

Help is needed to implement it, if possible.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.