hivesolutions / appier-extras Goto Github PK
View Code? Open in Web Editor NEWAppier on Steroids
Home Page: http://appier-extras.hive.pt
Appier on Steroids
Home Page: http://appier-extras.hive.pt
Creating a websocket like real-time communication is currently very hard under the Appier environment.
It should be possible to do this kind of integration for the Tasks
abstractions of the appier_admin infra-structure.
This issue is related to hivesolutions/appier#25
This feature should take inspiration in other node based implementations like Socket.io.
It should be possible to activate a feature in the login/authentication part of Appier Extras allowing external authentication to take place using OAuth. This would allow easy integration of OAuth for Apps using Appier Extras.
This feature is related with hivesolutions/appier#29.
There should be a simple workflow allowing proper authentication.
To be able to limit the requests frequency on an Appier instance it's important to have a decorator on such methods and be able to also apply a global limit via configuration.
This must be created recurring to a simple part called LimitPart .
Sometimes it's important to be able control the Parts that are included on a app dynamically at runtime. To be able to archive this a list based configuration variable must be used appier.conf("PARTS", cast = list)
.
The parts definition should be something like appier_extras.AdminPart
and the appier_extras packages should be included dynamically using the appier.import_pip(appier_extras
) this way it would be possible to include the admin part without setting appier extras on dependencies.
When defining a resizable image for e.g with:
avatar_data = utils.resize_image(
avatar.data, etag=avatar.etag, width=width, height=height
)
and later calling to get the output data using:
output_data = avatar_data.get_data()
it will throw the error `cannot access local variable 'resample':
UnboundLocalError
500 - cannot access local variable 'resample' where it is not associated with a value
File "/home/pc1/.local/lib/python3.11/site-packages/appier/base.py", line 1560, in application_l
result = self.handle()
File "/home/pc1/.local/lib/python3.11/site-packages/appier/base.py", line 1761, in handle
result = self.route()
File "/home/pc1/.local/lib/python3.11/site-packages/appier/base.py", line 2054, in route
return_v = method_i(*args, **kwargs)
File "/home/pc1/Documents/ripe-tech/ripe-id/src/ripe_id/controllers/web/account.py", line 171, in avatar
return account._send_avatar(
File "/home/pc1/.local/lib/python3.11/site-packages/appier_extras/parts/admin/models/account.py", line 697, in _send_avatar
return self.owner.send_file(
File "/home/pc1/.local/lib/python3.11/site-packages/appier/base.py", line 2945, in send_file
contents = contents()
File "/home/pc1/.local/lib/python3.11/site-packages/appier_extras/utils/image.py", line 63, in get_data
if resample == None:
This is related to a recent change.
Although the logic implemented makes sense and initially the method defines resample=None
in the python's locals, when we call the inner get_data
method, the resample
is no longer defined, probably due to a strange unexpected python interpreter response that cleans up the variable thinking it won't be used.
This was later verified to be true by changing the if resample == None: resample = (...)
to something else to not trick python interpreter into thinking that resample
will always be defined.
I think this is a very strange behavior and might be a python issue.
Incoming PR with a working fix suggestion.
Python 3.11.6
Currently operation parameters are described as a simple tuple
instance. A new appier.param()
structure must be creating inheriting from tuple and adding new functionaly, like named parameters.
Using it to provide support for the placeholder
value (eg: appier.param("name", placeholder = "Your name")
)
The model CRUD operations are not working as expected.
- | - |
---|---|
Expected | A model/entity can be created through /api/admin/models/<str:model> |
Observed | The POST /api/admin/models/<str:model> request returns the result for GET /api/admin/models |
POST
request with the URL http://ripe-core-now.platforme.com/api/admin/models/events{
"name": "order.created.swear",
"description": "order.created.swear",
"handler": "http",
"arguments": {
"name_r": "Order created #{params[payload][number]}",
"sender": "Platforme Reports <[email protected]>",
"title": "Order Created created #{params[payload][number]}",
"receivers": ["[email protected]"],
"subject": "Swear Order Created: #{params[payload][number]}"
}
}
GET
/api/admin/models
Key | Value |
---|---|
Device | iMac |
Operating System | macOS Catalina |
Instance (URL) | RIPE CORE NOW |
It may be relevant to keep multiple logins at the same time for fast switching.
The feature should be enabled or disabled using the ADMIN_MULTI_USER
config variable.
ADMIN_MULTI_USER
(bool
) - Controls if the multiple user login support should be enabled or not (defaults to True
)The overall implementation idea should follow the Omni guidelines.
A simple toolbar to be included in DEBUG mode so that some extra debug information (eg: SQL execution time, render time, queries, etc.) may be displayed and used.
It may be relevant to be able to define certain templates as markdown files that are processes and the HTML code is emitted.
Important use cases include the job posting for Hive Solutions and the blog for Hive Solutions.
It should be easy to implement this feature by using the filter based implementation as a reference.
https://github.com/hivesolutions/appier_extras/blob/master/src/appier_extras/parts/admin/part.py#L156
Sometimes it's relevant to keep storing the history/snapshot of an entity as backup that may be used latter to rollback unwanted changes.
For that a pre_update
(and pre_delete
) operation must be created that intercepts the storage operation and that retrieves a snapshot of the current state storing it on a different collection.
There should be a proper UI for retrieval (and inspection) of a different snapshot (snapshots collection).
Sometimes, it's relevant to increase the security of the authentication process by using 2FA, for instance, with a one-time password.
The additional layer of security can prevent attacks from malicious agents using a brute force password-targeted attack,
Some libraries for Python can handle the hardcore work (e.g., pyotp).
According to ChatGPT, this would be a valid implementation for a OTP based approach (eg: Google Authenticator).
import pyotp
def generate_secret():
# This will generate a fresh secret key
secret = pyotp.random_base32()
print(f"Secret key for user: {secret}")
return secret
def generate_otp(secret):
# Generate a TOTP object
totp = pyotp.TOTP(secret)
return totp.now() # Generate a OTP based on the current time
def verify_otp(secret, user_input):
# Verifies user input against the current OTP
totp = pyotp.TOTP(secret)
return totp.verify(user_input)
# Usage
user_secret = generate_secret()
otp = generate_otp(user_secret)
print(f"Generated OTP: {otp}")
# Simulate user entering OTP
user_otp_input = input("Enter the OTP: ")
if verify_otp(user_secret, user_otp_input):
print("OTP is correct!")
else:
print("Invalid OTP.")
Server side
from fido2.webauthn import PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity
from fido2.server import Fido2Server
from fido2.client import ClientData
from fido2.ctap2 import AttestationObject, AuthenticatorData
from fido2 import cbor
# Setup the relying party information
rp = PublicKeyCredentialRpEntity(name="Example Corp", id="localhost")
# User information (this should be dynamic in production use)
user = PublicKeyCredentialUserEntity(id=b"user_id", name="[email protected]", display_name="User")
# Initialize the server with the relying party details
server = Fido2Server(rp)
# Registration
def register_begin():
registration_data, state = server.register_begin({
"id": user.id,
"name": user.name,
"displayName": user.display_name,
})
return cbor.encode(registration_data), state
def register_complete(client_data, attestation_object, state):
client_data = ClientData(client_data)
attestation_obj = AttestationObject(attestation_object)
auth_data = server.register_complete(state, client_data, attestation_obj)
return auth_data.credential_data
# Authentication
def authenticate_begin():
auth_data, state = server.authenticate_begin(user)
return cbor.encode(auth_data), state
def authenticate_complete(client_data, authenticator_data, state):
client_data = ClientData(client_data)
auth_data = AuthenticatorData(authenticator_data)
server.authenticate_complete(state, user, client_data, auth_data)
return "Authentication successful!"
Client Side
# Simulate client operations for registration
client_data_json, state = register_begin()
# Normally client_data_json would be used by the client with the user's security key.
# For this example, assume we get the following from the client/security key.
client_data = b"{}" # Example client data, should be obtained from the security key
attestation_object = b"{}" # Example attestation object, should be obtained from the security key
# Complete registration
credential_data = register_complete(client_data, attestation_object, state)
print("Registration complete. Credential data:", credential_data)
# Simulate client operations for authentication
auth_data, state = authenticate_begin()
# Again, assume we get the necessary data from the client/security key.
client_data = b"{}"
authenticator_data = b"{}"
# Complete authentication
result = authenticate_complete(client_data, authenticator_data, state)
print(result)
Under production environments the stack-trace (error log) cannot be displayed directly to the end-user (user-agent) because of privacy issues.
The proper way to handle this is to store the stack trace (and other error information) in an external database and then provide the end-user user with an error tracing code (SHA 256) so that he can provide that to customer service and have the error diagnosed.
Exception
that stores all of this information in the data storeIn order to properly debug the various libraries loaded in the python runtime (eg: pillow, pymongo, etc) there should be an inverted system that automatically determines the various loaded modules and gathers the version numbers.
The implementation should be as simple and isolated as possible (may have to change the appier).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.