NAME

WWW::Suffit::AuthDB::Model - WWW::Suffit::AuthDB model (store) class

SYNOPSIS

use WWW::Suffit::AuthDB::Model;

my $model = WWW::Suffit::AuthDB::Model->new(
    "sqlite:///tmp/test.db?RaiseError=0&PrintError=0&sqlite_unicode=1"
);

my $model = WWW::Suffit::AuthDB::Model->new(
    "mysql://user:pass@mysql.example.com/authdb?mysql_auto_reconnect=1&mysql_enable_utf8=1"
);

die($model->error) unless $model->status;

DESCRIPTION

This module provides model methods

SQLITE DDL

CREATE TABLE IF NOT EXISTS "users" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "username"      CHAR(64) NOT NULL UNIQUE, -- User name
    "name"          CHAR(255) DEFAULT NULL, -- Full user name
    "email"         CHAR(255) DEFAULT NULL, -- Email address
    "password"      CHAR(255) NOT NULL, -- Password hash
    "algorithm"     CHAR(64) DEFAULT NULL, -- Password hash Algorithm (SHA256)
    "role"          CHAR(255) DEFAULT NULL, -- Role name
    "flags"         INTEGER DEFAULT 0, -- Flags
    "created"       INTEGER DEFAULT NULL, -- Created at
    "not_before"    INTEGER DEFAULT NULL, -- Not Before
    "not_after"     INTEGER DEFAULT NULL, -- Not After
    "public_key"    TEXT DEFAULT NULL, -- Public Key (RSA/X509)
    "private_key"   TEXT DEFAULT NULL, -- Private Key (RSA/X509)
    "attributes"    TEXT DEFAULT NULL, -- Attributes (JSON)
    "comment"       TEXT DEFAULT NULL -- Comment
);
CREATE TABLE IF NOT EXISTS "groups" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "groupname"     CHAR(64) NOT NULL UNIQUE, -- Group name
    "description"   TEXT DEFAULT NULL -- Description
);
CREATE TABLE IF NOT EXISTS "realms" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "realmname"     CHAR(64) NOT NULL UNIQUE, -- Realm name
    "realm"         CHAR(255) DEFAULT NULL, -- Realm string
    "satisfy"       CHAR(16) DEFAULT NULL, -- The satisfy policy (All, Any)
    "description"   TEXT DEFAULT NULL -- Description
);
CREATE TABLE IF NOT EXISTS "routes" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "realmname"     CHAR(64) DEFAULT NULL, -- Realm name
    "routename"     CHAR(64) DEFAULT NULL, -- Route name
    "method"        CHAR(16) DEFAULT NULL, -- HTTP method (ANY, GET, POST, ...)
    "url"           CHAR(255) DEFAULT NULL, -- URL
    "base"          CHAR(255) DEFAULT NULL, -- Base URL
    "path"          CHAR(255) DEFAULT NULL -- Path of URL (pattern)
);
CREATE TABLE IF NOT EXISTS "requirements" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "realmname"     CHAR(64) DEFAULT NULL, -- Realm name
    "provider"      CHAR(64) DEFAULT NULL, -- Provider name (user,group,ip and etc.)
    "entity"        CHAR(64) DEFAULT NULL, -- Entity (operand of expression)
    "op"            CHAR(2) DEFAULT NULL, -- Comparison Operator
    "value"         CHAR(255) DEFAULT NULL -- Test value
);
CREATE TABLE IF NOT EXISTS "grpsusrs" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "groupname"     CHAR(64) DEFAULT NULL, -- Group name
    "username"      CHAR(64) DEFAULT NULL -- User name
);
CREATE TABLE IF NOT EXISTS "meta" (
    "key"           CHAR(255) NOT NULL UNIQUE PRIMARY KEY,
    "value"         TEXT DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS "stats" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "address"       CHAR(40) DEFAULT NULL, -- IPv4/IPv6 client address
    "username"      CHAR(64) DEFAULT NULL, -- User name
    "dismiss"       INTEGER DEFAULT 0, -- Dismissal count
    "updated"       INTEGER DEFAULT NULL -- Update date
);
CREATE TABLE IF NOT EXISTS "tokens" (
    "id"            INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    "jti"           CHAR(32) DEFAULT NULL, -- Request ID
    "username"      CHAR(64) DEFAULT NULL, -- User name
    "type"          CHAR(20) DEFAULT NULL, -- Token type (session, refresh, api)
    "clientid"      CAHR(32) DEFAULT NULL, -- Clientid as md5 (User-Agent . Remote-Address)
    "iat"           INTEGER DEFAULT NULL, -- Issue time
    "exp"           INTEGER DEFAULT NULL, -- Expiration time
    "address"       CAHR(40) DEFAULT NULL -- IPv4/IPv6 client address
);

MYSQL DDL

CREATE DATABASE `authdb` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;
CREATE TABLE IF NOT EXISTS `users` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `username`      VARCHAR(64) NOT NULL, -- User name
    `name`          VARCHAR(255) DEFAULT NULL, -- Full user name
    `email`         VARCHAR(255) DEFAULT NULL, -- Email address
    `password`      VARCHAR(255) NOT NULL, -- Password hash
    `algorithm`     VARCHAR(64) DEFAULT NULL, -- Password hash Algorithm (SHA256)
    `role`          VARCHAR(255) DEFAULT NULL, -- Role name
    `flags`         INT(11) DEFAULT 0, -- Flags
    `created`       INT(11) DEFAULT NULL, -- Created at
    `not_before`    INT(11) DEFAULT NULL, -- Not Before
    `not_after`     INT(11) DEFAULT NULL, -- Not After
    `public_key`    TEXT DEFAULT NULL, -- Public Key (RSA/X509)
    `private_key`   TEXT DEFAULT NULL, -- Private Key (RSA/X509)
    `attributes`    TEXT DEFAULT NULL, -- Attributes (JSON)
    `comment`       TEXT DEFAULT NULL, -- Comment
    PRIMARY KEY (`id`),
    UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `groups` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `groupname`     VARCHAR(64) NOT NULL, -- Group name
    `description`   TEXT DEFAULT NULL, -- Description
    PRIMARY KEY (`id`),
    UNIQUE KEY `groupname` (`groupname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `realms` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `realmname`     VARCHAR(64) NOT NULL, -- Realm name
    `realm`         VARCHAR(255) DEFAULT NULL, -- Realm string
    `satisfy`       VARCHAR(16) DEFAULT NULL, -- The satisfy policy (All, Any)
    `description`   TEXT DEFAULT NULL, -- Description
    PRIMARY KEY (`id`),
    UNIQUE KEY `realmname` (`realmname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `routes` (
    `id`            INT NOT NULL AUTO_INCREMENT,
    `realmname`     VARCHAR(64) DEFAULT NULL, -- Realm name
    `routename`     VARCHAR(64) DEFAULT NULL, -- Route name
    `method`        VARCHAR(16) DEFAULT NULL, -- HTTP method (ANY, GET, POST, ...)
    `url`           VARCHAR(255) DEFAULT NULL, -- URL
    `base`          VARCHAR(255) DEFAULT NULL, -- Base URL
    `path`          VARCHAR(255) DEFAULT NULL, -- Path of URL (pattern)
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `requirements` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `realmname`     VARCHAR(64) DEFAULT NULL, -- Realm name
    `provider`      VARCHAR(64) DEFAULT NULL, -- Provider name (user,group,ip and etc.)
    `entity`        VARCHAR(64) DEFAULT NULL, -- Entity (operand of expression)
    `op`            VARCHAR(2) DEFAULT NULL, -- Comparison Operator
    `value`         VARCHAR(255) DEFAULT NULL, -- Test value
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `grpsusrs` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `groupname`     VARCHAR(64) DEFAULT NULL, -- Group name
    `username`      VARCHAR(64) DEFAULT NULL, -- User name
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `meta` (
    `key`           VARCHAR(255) NOT NULL,
    `value`         TEXT DEFAULT NULL,
    PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `stats` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `address`       VARCHAR(40) DEFAULT NULL, -- IPv4/IPv6 client address
    `username`      VARCHAR(64) DEFAULT NULL, -- User name
    `dismiss`       INT(11) DEFAULT 0, -- Dismissal count
    `updated`       INT(11) DEFAULT NULL, -- Update date
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `tokens` (
    `id`            INT(11) NOT NULL AUTO_INCREMENT,
    `jti`           VARCHAR(32) DEFAULT NULL, -- Request ID
    `username`      VARCHAR(64) DEFAULT NULL, -- User name
    `type`          VARCHAR(20) DEFAULT NULL, -- Token type (session, refresh, api)
    `clientid`      VARCHAR(32) DEFAULT NULL, -- Clientid as md5 (User-Agent . Remote-Address)
    `iat`           INT(11) DEFAULT NULL, -- Issue time
    `exp`           INT(11) DEFAULT NULL, -- Expiration time
    `address`       VARCHAR(40) DEFAULT NULL, -- IPv4/IPv6 client address
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

METHODS

new

my $model = WWW::Suffit::AuthDB::Model->new(
    "sqlite:///tmp/test.db?sqlite_unicode=1"
);

Creates DBI object

error

my $error = $model->error;

Returns error message

my $status = $model->error( "Error message" );

Sets error message if argument is provided. This method in "set" context returns status of the operation as status() method.

dbi

my $dbi = $model->dbi;

Returns CTK::DBI object of current database connection

dsn

my $dsn = $model->dsn;

Returns DSN string of current database connection

group_add

$model->group_add(
    groupname   => "wheel",
    description => "This administrator group added by default",
) or die($model->error);

Add new group recored

group_del

$model->group_del("wheel") or die($model->error);

Delete record by groupname

group_get

my %data = $model->group_get("wheel");

Returns data from database by groupname

group_getall

my @table = $model->group_getall();

Returns pure data from database

group_members

my @members = $model->group_members( "wheel" );

Returns members of specified group

group_set

$model->group_set(
    username    => "wheel",
    description => "This administrator group added by default",
) or die($model->error);

Update recored by groupname

grpusr_add

$model->grpusr_add(
    groupname   => "wheel",
    username    => "root",
) or die($model->error);

Add the user to the group

grpusr_del

$model->grpusr_del( id => 123 ) or die($model->error);
$model->grpusr_del( groupname => "wheel" ) or die($model->error);
$model->grpusr_del( username => "root" ) or die($model->error);

Delete members from groups by id, groupname or username

grpusr_get

my %data = $model->grpusr_get( id => 123 );
my @table = $model->grpusr_get( groupname => "wheel");
my @table = $model->grpusr_get( username => "root" );

Returns members of groups by id, groupname or username

init

Initialize DB instance. This method for internal use only

is_mysql

print $model->is_mysql ? "Is MySQL" : "Is NOT MySQL"

Returns true if type of current database is MySQL

is_oracle

print $model->is_oracle ? "Is Oracle" : "Is NOT Oracle"

Returns true if type of current database is Oracle

is_pg

print $model->is_pg ? "Is PostgreSQL" : "Is NOT PostgreSQL"

Returns true if type of current database is PostgreSQL

is_sqlite

print $model->is_sqlite ? "Is SQLite" : "Is NOT SQLite"

Returns true if type of current database is SQLite

meta_del

$model->meta_del("key") or die($model->error);

Delete record by key

meta_get

my %data = $model->meta_get("key");

Returns pair - key and value

my @table = $model->meta_get();

Returns all data from meta table

meta_set

$model->meta_set(key => "value") or die($model->error);

Set pair - key and value

ping

$model->ping ? 'OK' : 'Database session is expired';

Checks the connection to database

realm_add

$model->realm_add(
    realmname   => "root",
    realm       => "Root pages",
    satisfy     => "Any",
    description => "Index page",
) or die($model->error);

Add new realm recored

realm_del

$model->realm_del("root") or die($model->error);

Delete record by realmname

realm_get

my %data = $model->realm_get("root");

Returns data from database by realmname

realm_getall

my @table = $model->realm_getall();

Returns pure data from database

realm_requirement_add

$model->realm_requirement_add(
    realmname   => "root",
    provider    => "user",
    entity      => "username",
    op          => "eq",
    value       => "admin",
) or die($model->error);

Add the new requirement

realm_requirement_del

$model->realm_requirement_del("default") or die($model->error);

Delete requirements by realmname

realm_requirements

my @table = $model->realm_requirements("default");

Returns realm's requirements from database by realmname

realm_routes

my @table = $model->realm_routes( "realmname" );

Returns realm's routes from database by realmname

realm_set

$model->realm_set(
    realmname   => "root",
    realm       => "Root pages",
    satisfy     => "Any",
    description => "Index page (modified)",
) or die($model->error);

Update recored by realmname

reconnect

$model->reconnect;

This method performs reconnecting to database and returns model object

route_add

$model->route_add(
    realmname   => "root",
    routename   => "root",
    method      => "GET",
    url         => "https://localhost:8695/foo/bar",
    base        => "https://localhost:8695/`,
    path        => "/foo/bar",
) or die($model->error);

Add the new route to realm

route_del

$model->route_del(123) or die($model->error);

Delete record by id

$model->route_del("root") or die($model->error);

Delete record by realmname

route_release

$model->route_release("default") or die($model->error);

Releases the route (removes relation with realm) by realmname

route_assign

$model->route_add(
    realmname   => "default",
    routename   => "index",
) or die($model->error);

Assignees the realm for route by routename

route_get

my %data = $model->route_get(123);

Returns data from database by id

my @table = $model->route_get("root");

Returns data from database by realmname

route_getall

my @table = $model->route_getall();

Returns pure data from database

my @routes = $model->route_search( "ind" );

Performs search route by specified fragment and returns list of found routes

route_set

$model->route_set(
    id          => 123,
    realmname   => "root",
    routename   => "root",
    method      => "POST",
    url         => "https://localhost:8695",
    base        => "https://localhost:8695/`,
    path        => "/foo/bar",
) or die($model->error);

Update record by id

stat_get

my %st = $model->stat_get($address, $username);

Returns statistic information by address and username

stat_set

$model->stat_set(
    address => $address,
    username => $username,
    dismiss => 1,
    updated => time,
) or die($model->error);

Sets statistic information by address and username

status

my $status = $model->status;
my $status = $model->status( 1 ); # Sets the status value and returns it

Gets or sets the BOOL status of the operation

token_add

$model->token_add(
    type        => 'api',
    jti         => $jti,
    username    => $username,
    clientid    => 'qwertyuiqwertyui',
    iat         => time,
    exp         => time + 3600,
    address     => '127.0.0.1',
) or die($model->error);

Adds new token for user

token_del

$model->token_del( 123 ) or die($model->error);

Delete record by id

$model->token_del() or die($model->error);

Delete all expired tokens

token_get

my %data = $model->token_get( 123 );

Returns data from database by id

token_get_cond

my %data = $model->token_get_cond('api', username => $username, jti => $jti);
my %data = $model->token_get_cond('session', username => $username, clientid => $clientid);

Returns data from database by id jti or clientid

token_getall

my @table = $model->token_getall();

Returns all tokens

token_set

$model->token_set(
    id          => 123,
    type        => 'api',
    jti         => $jti,
    username    => $username,
    clientid    => 'qwertyuiqwertyui',
    iat         => time,
    exp         => time + 3600,
    address     => '127.0.0.1',
) or die($model->error);

Update record by id

user_add

$model->user_add(
    username    => "admin",
    name        => "Administrator",
    email       => 'root@localhost',
    password    => "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
    algorithm   => "SHA256",
    role        => "System administrator",
    flags       => 0,
    created     => time(),
    not_before  => time(),
    not_after   => undef,
    public_key  => "",
    private_key => "",
    attributes  => qq/{"disabled": 0}/,
    comment     => "This user added by default",
) or die($model->error);

Add new user recored

user_del

$model->user_del("admin") or die($model->error);

Delete record by username

user_edit

$model->user_edit(
    id          => 123,
    username    => $username,
    comment     => $comment,
    email       => $email,
    name        => $name,
    role        => $role,
) or die($model->error);

Edit user data by id

user_get

my %data = $model->user_get("admin");

Returns data from database by username

user_getall

my @table = $model->user_getall();

Returns pure data from database (array of hash)

user_groups

my @groups = $model->user_groups( "admin" );

Returns groups of specified user

user_passwd

$model->user_passwd(
    username    => "admin",
    password    => "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
) or die($model->error);

Changes password for user

my @users = $model->user_search( "ad" );

Performs search user by specified fragment and returns list of found users

user_set

$model->user_set(
    username    => "admin",
    name        => "Administrator",
    email       => 'root@localhost',
    password    => "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
    algorithm   => "SHA256",
    role        => "System administrator",
    flags       => 0,
    not_before  => time(),
    not_after   => undef,
    public_key  => "",
    private_key => "",
    attributes  => qq/{"disabled": 0}/,
    comment     => "This user added by default",
) or die($model->error);

Update recored by username

user_setkeys

$model->user_setkeys(
    id          => 123,
    public_key  => $public_key,
    private_key => $private_key,
) or die($model->error);

Sets keys to user's data

user_tokens

my @table = $model->user_tokens($username);

Returns all tokens for user

HISTORY

See Changes file

TO DO

See TODO file

SEE ALSO

WWW::Suffit::AuthDB, CTK::DBI

AUTHOR

Serż Minus (Sergey Lepenkov) https://www.serzik.com <abalama@cpan.org>

COPYRIGHT

Copyright (C) 1998-2023 D&D Corporation. All Rights Reserved

LICENSE

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See LICENSE file and https://dev.perl.org/licenses/