Alpha API system
Introduction
The api system is completely based on Flask and compatible. You could use Flask inside Alpha system without any issue.
Launch
To start the api execute the api.py
file
python api.py
Note
set ALPHA_CONF
environment parameter is you want to set the environment.
Verify the deployment by navigating to your server address in your preferred browser:
127.0.0.1:<port>
How to use
Your could import it using simply from the utils:
from alphaz.utils.api import api
or from the core if you are using it
from core import core, API
api / API is the equivalent for app in Flask framework.
Routes
We recommend to add all the route definition in apis/routes folder and import all the route definition in apis/routes/init.py.
Then you will have to import the route in thoe core.py file:
from alphaz.models.main import AlphaCore, singleton
@singleton
class Core(AlphaCore):
def __init__(self,file:str):
super().__init__(file)
core = Core(__file__)
DB, API, LOG = core.db, core.api, core.log # not required but recommanded
from apis.routes import *
Configuration
The api is automatically configured from the api.jon
file. See Configuration for further details on how to use it.
Main
- workers: In order to specify the numbers of workers
"workers": 6
- routes_no_log: In order to specify the routes where log must be ignored
"routes_no_log": ["//status", "//static", "//dashboard"],
- models: In order to specify the Flask-SqlAlchemy models definitions paths
"models": ["models.databases"]
- routes: In order to specify the routes definitions paths
"routes": ["apis.routes"]
- ssl: In order to activate ssl mode
"ssl": false
- threaded: In order to activate the threaded mode
"threaded": false
- config: In order to activate pass configuration to Flask api class
"config": {
"MYSQL_DATABASE_CHARSET": "utf8mb4",
"SQLALCHEMY_TRACK_MODIFICATIONS": false,
"SQLALCHEMY_POOL_RECYCLE": 299,
"SQLALCHEMY_POOL_TIMEOUT": 30,
"SQLALCHEMY_POOL_SIZE": 10,
"JWT_SECRET_KEY": "a_secret_key",
"JSON_SORT_KEYS": false
}
Mails
In order to specify the mails configurations
"mails": {
"mail_server": {
"host": "",
"mail": "",
"password": "",
"port": 465,
"server": "",
"ssl": true,
"tls": false
}
}
Auth
In order to specify the auth mode
"auth": {
"mode": "ldap",
"ldap": {
"server": "ldap://path_to_ldap",
"baseDN": "ou=people,dc=a_name,dc=com",
"users_filters": "(|(uid={uid})(mail={mail})(cn={cn}))",
"user_filters": "(|(uid={username})(mail={username})(cn={username}))",
"user_data": {
"givenName": "name",
"sn": "lastname",
"c": "area",
"st-locationdescription": "location",
"st-seatnumber": "seat",
"telephoneNumber": "phone-number"
}
},
"users": {
"a_user_name": {
"user_permissions": ["SUPER_USER"]
}
}
},
Reloader type
In order to specify the Werkzeug reloader type
"reloader_type": "stat"
Admin
In order to specify the admins configurations
"admins": {"ips":["127.0.0.1"], "password":"a_password"},
Dashboard
In order to configure the Flask-Monitoring Dashboard
"dashboard": {
"dashboard": {
"APP_VERSION": 1.0,
"SAMPLING_PERIOD": 20,
"ENABLE_LOGGING": true,
"active": false
},
"authentication": {
"USERNAME": "username",
"PASSWORD": "",
"GUEST_USERNAME": "guest",
"GUEST_PASSWORD": ["guest1", "guest2"],
"SECURITY_TOKEN": "a_security_token"
},
"database": {
"DATABASE": "sqlite:///{{root}}/dashboard.db"
}
}
Routes
Basic
To specify an api route, juste use the route
flag:
from alphaz.utils.api import route, api, Parameter
@route("route_name")
def method_name():
return "hello"
Method automatically convert the output to the right format. Default format is json
Description
A description could be specified:
@route("route_name", description="This route say hello")
def method_name():
return "hello"
Category
The routes are organized by category
, by default the route category is defined by it file name, but it could be specified using the cat
parameter:
@route("route_name", category="politeness")
def method_name():
return "hello"
Parameters
Simple
You could simply define parameters by listing all parameters in parameters
list:
from alphaz.utils.api import route, api, Parameter
@route("books", parameters=["name"])
def method_name():
return "Book name is %s or %s"%(api["name"], api.get("name",default=""))
Parameter value is accessed by api
instance, using get
method, they could also be accessed using get_parameters
method from api
instance.
Object
Or you could use the Parameter
class to specify properties such as:
- ptype: value type int, str, bool,
SqlAlchemy model
- parameter is
automatically converted
to the specified type - if conversion failed an
exception
is raised - required: the parameter is required or not
- default: default parameter value
- options: authorized values
- mode: input mode
- cacheable: parameter is taken into acount in the caching system or not
- private: parameter is hiden from documentation or not
@route("/logs",
parameters = [
Parameter('page',required=True,ptype=int),
Parameter('startDate',required=True),
Parameter('endDate',default=None),
Parameter('error', options=["Y","N"])
])
def admin_logs():
return get_logs(**api.get_parameters())
Promote this method as it allows a better control on parameters
Default parameters
Some parameter are always available: - no_log (bool): disable logs for this route - reset_cache (bool): reset cache before calling this route - requester (str): requester to this route - format (str): output format - json: - xml: - admin (str): admin password - admin_user_id (int): id of the user to connect has an admin
SqlAlchemy model
If you specify a SqlAlchemy model
as a type it will be automatically converted to the specified model.
from core import core
db = core.db
class Logs(db.Model, AlphaTable):
__tablename__ = 'LOGS'
id = AlphaColumn(Integer,nullable=False,primary_key=True)
name = AlphaColumn(String,nullable=False)
@route("logs",
parameters = [
Parameter('log',ptype=Logs)
])
def admin_logs():
db.add(api['log'])
Methods
Methods are specified the same way as in Flask
, using methods
parameter:
@route('logs', methods=["GET"])
def get_logs():
return db.select(Logs)
@route('logs', methods=["POST"])
def set_logs():
return db.add(Logs)
Methods can be managed using different routes
or within a single route
:
@route('logs', methods=["GET", "POST", "DELETE"])
def get_logs():
if api.is_get():
return db.select(Logs)
elif api.is_post():
return db.add(Logs)
elif api.is_delete():
return db.delete(Logs)
Authorizations
Route can be protected using the login system or admin rights.
Login system
To protect a route using the login system you must specify: logged=True
@route('protected', logged=True)
def protected_route():
user = api.get_logged_user()
return user
User information can be accessed using get_logged_user method.
Cache
A cache system is implemented, in order to use it you must specify the
Admin
Admin could auto log to any user account on local mode
Condition
To be an admin a user must have at least one condition:
- a role > 9
- specify the magic password has admin API parameter
- connect using an admin ip. The ips admin list must be defined in the api.json configuration files under the key=admins_ips
How to use
If you met one of the admin condition you do not need any password in order to log has any of the user in the database.
You could be logged for specific routes using the single route mode or to any route using the login/logout system.
Single route mode
- You could specifiy either admin_user_id={user_id} or admin_user_name={username} directly into any request in order to login with this user for this specific route.
Exemple
/anyroute?admin_user_id=1000
Login to the api
Use the route /auth/su in order to set an admin session that is valid until the end of the api runtime.
- You must specifiy either admin_user_id={user_id} or admin_user_name={username}
Exemple
/auth/su?admin_user_id=1000
Logout from the api
Use the route /logout/su in order to logout.
Issues
In progress
Database alias
In progress