| 113 | | * '''Principle of Least Privilege (PoLP):''' The live web application authenticates using a dedicated runtime role (`app_runner`) restricted exclusively to DML operations (`SELECT`, `INSERT`, `UPDATE`). Destructive or structural privileges like `DROP`, `ALTER`, or schema catalog edits are blocked. |
| 114 | | * '''Handling Dynamic Queries Safely:''' Internal procedures or complex triggers generating dynamic SQL paths utilize native safe encapsulation routines (`quote_ident()` and `quote_literal()`) to protect executing buffers from raw injections. |
| 115 | | * '''Network and Transport Security:''' Database sockets are bound strictly to private loopback interfaces (`127.0.0.1`) and secure VPC spaces, completely shielding administrative ports from external public networks. |
| | 111 | * '''Prevention of SQL Injection in Dynamic Queries:''' Avoiding the manual execution of raw string formatting (f-strings or %s concatenation). All dynamically evaluated filtering explicitly passes parameter tuples. |
| | 112 | * '''Prevention of Un-authorized Access to Data:''' Multi-tenant structural architecture where every row manipulation isolates and constraints queries via a verified `tenant_id`. |
| | 113 | |
| | 114 | --- |
| | 115 | |
| | 116 | == Other Developments == |
| | 117 | |
| | 118 | === JWT автентикација и авторизација === |
| | 119 | Системот користи JWT (JSON Web Token) за автентикација на корисниците по успешна Google најава. |
| | 120 | |
| | 121 | Процесот се состои од следните чекори: |
| | 122 | 1. Корисникот се најавува преку Google OAuth. |
| | 123 | 2. Серверот го верификува Google токенот. |
| | 124 | 3. Доколку најавата е успешна, серверот креира JWT токен кој содржи: `user_id`, `email`, `role`, `tenant_id`. |
| | 125 | 4. JWT токенот се зачувува во HttpOnly cookie со име `session`. |
| | 126 | 5. При секое наредно барање прелистувачот автоматски го испраќа cookie-то. |
| | 127 | 6. Серверот го верификува JWT токенот и ги чита корисничките информации. |
| | 128 | |
| | 129 | '''Креирање на JWT токен:''' |
| | 130 | {{{ |
| | 131 | #!python |
| | 132 | def make_jwt(payload: dict, minutes=60 * 24): |
| | 133 | exp = datetime.utcnow() + timedelta(minutes=minutes) |
| | 134 | data = {**payload, "iss": JWT_ISSUER, "exp": exp} |
| | 135 | return jwt.encode(data, JWT_SECRET, algorithm="HS256") |
| | 136 | }}} |
| | 137 | |
| | 138 | '''Проверка на JWT токен:''' |
| | 139 | {{{ |
| | 140 | #!python |
| | 141 | def read_jwt(token: str): |
| | 142 | return jwt.decode( |
| | 143 | token, |
| | 144 | JWT_SECRET, |
| | 145 | algorithms=["HS256"], |
| | 146 | issuer=JWT_ISSUER |
| | 147 | ) |
| | 148 | }}} |
| | 149 | |
| | 150 | Пристапот до заштитените API рути е овозможен преку декораторите `@require_user` и `@require_tenant_admin`. |
| | 151 | {{{ |
| | 152 | #!python |
| | 153 | @require_user() |
| | 154 | def api_me(): |
| | 155 | ... |
| | 156 | }}} |
| | 157 | |
| | 158 | === CORS конфигурација === |
| | 159 | Бидејќи frontend апликацијата и Flask серверот работат на различни адреси, потребно е овозможување на Cross-Origin Resource Sharing (CORS). |
| | 160 | |
| | 161 | Во системот е конфигурирана листа на дозволени домени: |
| | 162 | {{{ |
| | 163 | #!python |
| | 164 | DEFAULT_ORIGINS = [ |
| | 165 | "http://localhost:5173", |
| | 166 | "http://127.0.0.1:5173", |
| | 167 | ] |
| | 168 | }}} |
| | 169 | |
| | 170 | Конфигурацијата се извршува преку Flask-CORS: |
| | 171 | {{{ |
| | 172 | #!python |
| | 173 | CORS( |
| | 174 | app, |
| | 175 | supports_credentials=True, |
| | 176 | origins=ALLOWED_ORIGINS, |
| | 177 | allow_headers=[ |
| | 178 | "Content-Type", |
| | 179 | "X-Admin-Session", |
| | 180 | "X-Env", |
| | 181 | "X-Env-Token", |
| | 182 | ], |
| | 183 | methods=["GET", "POST", "OPTIONS"], |
| | 184 | ) |
| | 185 | }}} |
| | 186 | * Се дозволуваат барања само од доверливи frontend адреси. |
| | 187 | * Се дозволува испраќање на JWT cookie преку `supports_credentials=True`. |
| | 188 | * Се ограничуваат HTTP методите на GET, POST и OPTIONS. |
| | 189 | * Се контролира кои HTTP заглавија може да се испраќаат кон серверот. |
| | 190 | |
| | 191 | === Безбедносен модел === |
| | 192 | Системот користи повеќеслојна безбедност: |
| | 193 | * Google OAuth за верификација на идентитетот. |
| | 194 | * JWT токени за одржување на корисничка сесија. |
| | 195 | * HttpOnly cookies за заштита од JavaScript пристап до токените. |
| | 196 | * CORS политика за ограничување на дозволените клиентски апликации. |
| | 197 | * Tenant изолација преку `tenant_id`. |
| | 198 | * Посебни environment токени (`X-Env-Token`) за комуникација помеѓу агентите и серверот. |