Merge branch 'spring_security'
This commit is contained in:
commit
8aa8e0f5fc
@ -0,0 +1,913 @@
|
||||
{
|
||||
"info": {
|
||||
"_postman_id": "721d5504-301f-488d-a25b-5e78769eac5a",
|
||||
"name": "CezenPBX_API",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||
"_exporter_id": "29498098"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "create a new endpoint",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": \"1005\",\n// \"transport\": \"transport-udp\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n \"connectedLineMethod\": null,\n \"callerid\": null,\n \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n \"mailboxes\": null\n}\n\n// {\n// \"id\": \"1004\",\n// \"transport\": \"transport-udp\",\n// \"aors\": \"1004\",\n// \"auth\": \"1004\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n// \"connectedLineMethod\": null,\n// \"callerid\": \"User <1004>\",\n// \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n// \"mailboxes\": \"1004@default\"\n// }",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_user",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_user"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "create a new extension",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"context\": \"default\",\n \"extension\": \"1005\",\n \"priority\": 1,\n \"app\": \"Dial\",\n \"appdata\": \"PJSIP/1005,20,m(default)\"\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_extension",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_extension"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "1005",
|
||||
"originalRequest": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"context\": \"default\",\n \"extension\": \"1005\",\n \"priority\": 1,\n \"app\": \"Dial\",\n \"appdata\": \"PJSIP/1005,20,m(default)\"\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_extension",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_extension"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:20:09 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": false,\n \"message\": \"Data likely already exists or DB issue\",\n \"exceptionMessage\": \"could not execute statement [(conn=482) Duplicate entry '1005-PJSIP/1005,20,m(default)-1' for key 'extension_table_unique_val'] [insert into extensions_table (app,appdata,context,exten,priority) values (?,?,?,?,?)]; SQL [insert into extensions_table (app,appdata,context,exten,priority) values (?,?,?,?,?)]; constraint [extension_table_unique_val]\"\n}"
|
||||
},
|
||||
{
|
||||
"name": "test1",
|
||||
"originalRequest": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"context\": \"default\",\n \"extension\": \"test1\",\n \"priority\": 1,\n \"app\": \"Dial\",\n \"appdata\": \"test123rf\"\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_extension",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_extension"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:21:06 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": true,\n \"message\": \"test1 Persisted \",\n \"exceptionMessage\": \"\"\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set_password",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": \"1005\",\n \"authType\": \"userpass\",\n \"userName\": \"1005\",\n \"password\": \"12345\",\n \"md5Cred\": null,\n \"realm\": null\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/set_password",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"set_password"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "set_password",
|
||||
"originalRequest": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": \"1005\",\n \"authType\": \"userpass\",\n \"userName\": \"1005\",\n \"password\": \"12345\",\n \"md5Cred\": null,\n \"realm\": null\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/set_password",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"set_password"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:21:54 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": false,\n \"message\": \"Endpoint and password already set \",\n \"exceptionMessage\": \"could not execute statement [(conn=482) Duplicate entry '1005' for key 'PRIMARY'] [insert into ps_auths (auth_type,md5_cred,password,realm,username,id) values (?,?,?,?,?,?)]; SQL [insert into ps_auths (auth_type,md5_cred,password,realm,username,id) values (?,?,?,?,?,?)]; constraint [PRIMARY]\"\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SetAORS",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": \"1005\",\n \"maxContacts\": 1\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/set_aors",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"set_aors"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "SetAORS",
|
||||
"originalRequest": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": \"1005\",\n \"maxContacts\": 1\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/set_aors",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"set_aors"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:22:12 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": true,\n \"message\": \"1005 Persisted \",\n \"exceptionMessage\": \"\"\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteExtension",
|
||||
"request": {
|
||||
"method": "DELETE",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/delete_extension?sipNumber=testEndPoint",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"delete_extension"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "sipNumber",
|
||||
"value": "testEndPoint"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "DeleteExtension",
|
||||
"originalRequest": {
|
||||
"method": "DELETE",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/delete_extension?sipNumber=1005",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"delete_extension"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "sipNumber",
|
||||
"value": "1005"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:22:35 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "true"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Add_a_global_extension_feature",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"context\": \"default\",\n \"extension\": \"w\",\n \"priority\": 5,\n \"app\": \"Dial\",\n \"appdata\": \"W conf\"\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_feature",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_feature"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "Add_a_global_extension_feature",
|
||||
"originalRequest": {
|
||||
"method": "PUT",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"context\": \"default\",\n \"extension\": \"w\",\n \"priority\": 5,\n \"app\": \"Dial\",\n \"appdata\": \"W conf\"\n}\n",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/cezen/add_feature",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"cezen",
|
||||
"add_feature"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 10:53:48 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": false,\n \"message\": \"w configured as default Already exists\",\n \"exceptionMessage\": \"jakarta.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call\"\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "signup",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"userName\": \"Mathew Francis\",\n \"email\":\"asda@gmail.com\",\n \"password\": \"1234567890\",\n \"confirmPassword\": \"1234567890\"\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/open/signup",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"open",
|
||||
"signup"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "login",
|
||||
"protocolProfileBehavior": {
|
||||
"disableBodyPruning": true
|
||||
},
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "basic",
|
||||
"basic": [
|
||||
{
|
||||
"key": "password",
|
||||
"value": "1234",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "username",
|
||||
"value": "mathew",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": ""
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/open/login",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"open",
|
||||
"login"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"name": "login",
|
||||
"originalRequest": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": ""
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/open/login",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"open",
|
||||
"login"
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"_postman_previewlanguage": "json",
|
||||
"header": [
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Origin"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Method"
|
||||
},
|
||||
{
|
||||
"key": "Vary",
|
||||
"value": "Access-Control-Request-Headers"
|
||||
},
|
||||
{
|
||||
"key": "Set-Cookie",
|
||||
"value": "Authorization=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJNYXRoZXcgRnJhbmNpcyIsInN1YiI6IkpXVF9Ub2tlbiIsInVzZXJuYW1lIjoiY29tLmV4YW1wbGUuY2V6ZW5QQlguZW50aXR5LnVzZXIuVXNlckVudGl0eUAzMGI5ZjFlOCIsImF1dGhvcml0aWVzIjoiUk9MRV9hZG1pbiIsImlhdCI6MTc0NzI5MDAyMCwiZXhwIjoxNzQ3MzIwMDIwfQ.kjyArki3Cbc90Jjf68pl5iPeg61GWaxb6yT6ivTNXes; Path=/; Secure; HttpOnly"
|
||||
},
|
||||
{
|
||||
"key": "X-Content-Type-Options",
|
||||
"value": "nosniff"
|
||||
},
|
||||
{
|
||||
"key": "X-XSS-Protection",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, max-age=0, must-revalidate"
|
||||
},
|
||||
{
|
||||
"key": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"key": "Expires",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"key": "X-Frame-Options",
|
||||
"value": "DENY"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Transfer-Encoding",
|
||||
"value": "chunked"
|
||||
},
|
||||
{
|
||||
"key": "Date",
|
||||
"value": "Thu, 15 May 2025 06:20:20 GMT"
|
||||
},
|
||||
{
|
||||
"key": "Keep-Alive",
|
||||
"value": "timeout=60"
|
||||
},
|
||||
{
|
||||
"key": "Connection",
|
||||
"value": "keep-alive"
|
||||
}
|
||||
],
|
||||
"cookie": [],
|
||||
"body": "{\n \"status\": false,\n \"message\": \"Login not yet implemented\",\n \"exceptionMessage\": \"Login not yet implemented\"\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "logout",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "http://localhost:8081/logout",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8081",
|
||||
"path": [
|
||||
"logout"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
}
|
||||
102
MySQL_conf_pbx/test1/db_asterisk/security.sql
Normal file
102
MySQL_conf_pbx/test1/db_asterisk/security.sql
Normal file
@ -0,0 +1,102 @@
|
||||
USE asterisk_db;
|
||||
|
||||
SHOW DATABASES;
|
||||
|
||||
SHOW TABLES;
|
||||
|
||||
|
||||
SELECT * FROM `ps_endpoints`;
|
||||
|
||||
DELETE FROM `ps_endpoints` WHERE `id` = '1004';
|
||||
|
||||
SELECT * FROM `extensions_table`;
|
||||
DESCRIBE `extensions_table`;
|
||||
|
||||
ALTER TABLE `extensions_table`
|
||||
ADD CONSTRAINT `extension_table_unique_val_two_check` UNIQUE (`exten`, `appdata`);
|
||||
|
||||
|
||||
ALTER TABLE `extensions_table`
|
||||
DROP INDEX `extension_table_unique_val`;
|
||||
|
||||
|
||||
ALTER TABLE `extensions_table`
|
||||
ADD CONSTRAINT `extension_table_unique_val` UNIQUE (`exten`, `appdata`, `priority`);
|
||||
|
||||
DELETE FROM `extensions_table` WHERE priority = 4 and exten = "1005" ;
|
||||
DELETE FROM `extensions_table` WHERE exten = "1005" OR exten = "1004";
|
||||
|
||||
DELETE FROM `ps_endpoints` WHERE id = "1004" OR id = "1005";
|
||||
DELETE FROM `extensions_table` WHERE exten = "1004" OR exten = "1005";
|
||||
|
||||
DELETE FROM `ps_auths` WHERE id = "1004" OR id = "1005";
|
||||
DELETE FROM `ps_aors` WHERE id = "1004" OR id = "1005";
|
||||
|
||||
SELECT * FROM `extensions_table` WHERE app = "Dial";
|
||||
SELECT * FROM extensions_table WHERE context = 'default' AND exten = '1005';
|
||||
SELECT * FROM extensions_table WHERE exten = '1004' AND context = 'default';
|
||||
|
||||
|
||||
|
||||
SELECT * FROM `ps_endpoints`;
|
||||
SELECT * FROM `extensions_table`;
|
||||
--
|
||||
SELECT * FROM ps_auths;
|
||||
SELECT * FROM ps_aors;
|
||||
DESCRIBE `ps_auths`;
|
||||
DESCRIBE `ps_aors`;
|
||||
DESCRIBE `extensions_table`;
|
||||
|
||||
INSERT INTO `ps_aors`(`id`,`max_contacts`) VALUES ("1004", 1);
|
||||
INSERT INTO `ps_auths`(`id`, `auth_type`, `username`, `password`, `md5_cred`, `realm`) VALUES("1004", "userpass", "1004", "12345", null, null);
|
||||
|
||||
|
||||
|
||||
|
||||
-- USER ROLES ROLE GOES HERE
|
||||
CREATE TABLE `roles`(
|
||||
`role_id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`role_name` VARCHAR(20) UNIQUE NOT NULL,
|
||||
CONSTRAINT `roles_pk` PRIMARY KEY (`role_id`)
|
||||
)ENGINE = 'Innodb' AUTO_INCREMENT = 1, DEFAULT CHARSET 'latin1';
|
||||
|
||||
DESCRIBE `roles`;
|
||||
|
||||
|
||||
CREATE TABLE `user_roles`(
|
||||
`u_id` INTEGER NOT NULL,
|
||||
`role_id` INTEGER NOT NULL,
|
||||
CONSTRAINT `user_roles_pk` PRIMARY KEY(`u_id`,`role_id`)
|
||||
)ENGINE = 'Innodb' AUTO_INCREMENT = 1, DEFAULT CHARSET 'latin1';
|
||||
|
||||
|
||||
-- foreign key to be added to this table in alter table form
|
||||
CREATE TABLE `user`(
|
||||
`u_id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`user_name` VARCHAR(70) UNIQUE NOT NULL,
|
||||
`password` VARCHAR(68) NOT NULL,
|
||||
-- fk to uder_account
|
||||
CONSTRAINT `user_table_pk` PRIMARY KEY(`u_id`)
|
||||
)ENGINE = 'Innodb', AUTO_INCREMENT = 1, DEFAULT CHARSET 'latin1';
|
||||
|
||||
ALTER TABLE `user` ADD COLUMN `user_email_id` VARCHAR(50) UNIQUE NOT NULL;
|
||||
|
||||
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_lones_U_fk_to_user` FOREIGN KEY(`u_id`) REFERENCES `user`(`u_id`);
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_lones_R_fk_to_user` FOREIGN KEY(`role_id`) REFERENCES `roles`(`role_id`);
|
||||
DESC `user_roles`;
|
||||
|
||||
|
||||
INSERT `roles`(`role_name`) VALUES ('ROLE_admin');
|
||||
|
||||
SELECT * FROM `user`;
|
||||
SELECT * FROM `user_roles`;
|
||||
SELECT * FROM `roles`;
|
||||
|
||||
DELETE FROM `user` WHERE `user_name` = 'Mathew Francis';
|
||||
DELETE FROM `user_roles` WHERE `u_id` = (SELECT `u_id` FROM `user_roles` LIMIT 1);
|
||||
DELETE FROM `roles` WHERE `roles`.`role_name` = 'ROLE_admin'
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.frm
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.frm
Normal file
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd
Normal file
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.frm
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.frm
Normal file
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd
Normal file
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.frm
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.frm
Normal file
Binary file not shown.
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd
Normal file
BIN
MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -70,6 +70,35 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<!-- spring security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JWT dependency -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.12.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.12.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.12.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -8,6 +8,7 @@ import jakarta.persistence.TypedQuery;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.UnexpectedRollbackException;
|
||||
|
||||
@Repository
|
||||
public class BasicAsteriskOpsDAO implements CezenPbxOpsDAO {
|
||||
@ -114,21 +115,21 @@ public class BasicAsteriskOpsDAO implements CezenPbxOpsDAO {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ReturnStatus saveAnExtensionByCharacters(ExtensionsTable extensionsTable) {
|
||||
|
||||
try{
|
||||
|
||||
this.entityManager.persist(extensionsTable);
|
||||
|
||||
try {
|
||||
this.doPersist(extensionsTable); // calls @Transactional method
|
||||
return new ReturnStatus(true,
|
||||
extensionsTable.getExtension() +" configured as "+ extensionsTable.getContext() +" added",
|
||||
"");
|
||||
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
return new ReturnStatus(false,
|
||||
extensionsTable.getExtension() +" configured as "+ extensionsTable.getContext() +" Already exists",
|
||||
e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void doPersist(ExtensionsTable extensionsTable) {
|
||||
entityManager.persist(extensionsTable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.example.cezenPBX.DAO;
|
||||
|
||||
import com.example.cezenPBX.DTO.ReturnStatus;
|
||||
import com.example.cezenPBX.entity.user.UserEntity;
|
||||
|
||||
// TODO only one admin allowed ... once the admin creates an
|
||||
// account they should not be able to make the account again
|
||||
// admin login, logout and signup DAO operations
|
||||
public interface UserOpsDAO {
|
||||
|
||||
// check if user exists;
|
||||
public boolean checkIfAdminExists(UserEntity userEntity) throws Exception;
|
||||
|
||||
// admin login
|
||||
public ReturnStatus adminSetUsernameAndPassword(UserEntity userEntity);
|
||||
|
||||
public UserEntity getUserByUserName(String userName);
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.example.cezenPBX.DAO;
|
||||
|
||||
import com.example.cezenPBX.DTO.ReturnStatus;
|
||||
import com.example.cezenPBX.entity.user.Role;
|
||||
import com.example.cezenPBX.entity.user.UserEntity;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.Query;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class UserOpsDAOImpl implements UserOpsDAO{
|
||||
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Override
|
||||
public boolean checkIfAdminExists(UserEntity userEntity){
|
||||
// check if info exists in the database users table
|
||||
// this enforces the fact that only one user can exist
|
||||
Query query = entityManager.createQuery(
|
||||
"SELECT COUNT(u) FROM UserEntity u JOIN u.roles r WHERE r.role = :roleName");
|
||||
query.setParameter("roleName", "ROLE_Admin");
|
||||
Long count = (Long) query.getSingleResult();
|
||||
return count > 0;
|
||||
|
||||
}
|
||||
|
||||
// get roles from the database
|
||||
|
||||
// Admin sets a username and password for the first time
|
||||
@Override
|
||||
@Transactional
|
||||
public ReturnStatus adminSetUsernameAndPassword(UserEntity userEntity) {
|
||||
|
||||
try {
|
||||
if (checkIfAdminExists(userEntity)) {
|
||||
return new ReturnStatus(false, "Admin already exists", "");
|
||||
}
|
||||
// Fetch existing ROLE_Admin from DB
|
||||
TypedQuery<Role> query = entityManager.createQuery("FROM Role r WHERE r.role = :roleName", Role.class)
|
||||
.setParameter("roleName", "ROLE_Admin");
|
||||
|
||||
Role role = query.getSingleResult();
|
||||
|
||||
userEntity.setARole(role);
|
||||
// Persist the user
|
||||
entityManager.persist(userEntity);
|
||||
return new ReturnStatus(true, "Admin created", "");
|
||||
} catch (Exception e) {
|
||||
return new ReturnStatus(false, "Admin creation failed", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// get user details by username
|
||||
// throws an exception if the user doesn't exist
|
||||
// exception is caught and returns null ... custom authentication provider must catch the exception
|
||||
@Override
|
||||
public UserEntity getUserByUserName(String userName) {
|
||||
|
||||
try{
|
||||
TypedQuery<UserEntity> query = this.entityManager
|
||||
.createQuery("SELECT u FROM UserEntity u JOIN FETCH u.roles AS r WHERE u.userName = :userName", UserEntity.class);
|
||||
|
||||
query.setParameter("userName", userName);
|
||||
|
||||
return query.getSingleResult();
|
||||
|
||||
}catch ( Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.example.cezenPBX.DTO.user;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record AdminSetPasswordDTO(
|
||||
@NotBlank(message = "Username cannot be blank")
|
||||
String userName,
|
||||
|
||||
@Email(message = "Email is not valid")
|
||||
String email,
|
||||
|
||||
@NotBlank(message = "Password cannot be blank")
|
||||
@Size(min = 3, message = "Password must be at least 8 characters long")
|
||||
String password,
|
||||
|
||||
@NotBlank(message = "Confirm password cannot be blank")
|
||||
String confirmPassword
|
||||
) {}
|
||||
@ -0,0 +1,112 @@
|
||||
package com.example.cezenPBX.config;
|
||||
|
||||
|
||||
import com.example.cezenPBX.security.JWTTokenGeneratorFilter;
|
||||
import com.example.cezenPBX.security.JWTTokenValidatorFilter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
// this class will handel the routs that are protected and
|
||||
// allow spring security to accept login details from our custom login page
|
||||
@Configuration
|
||||
public class CezenLoginSecurityChain {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||
|
||||
//the token is generated here
|
||||
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
|
||||
requestHandler.setCsrfRequestAttributeName("_csrf");
|
||||
|
||||
//CSRF cookie
|
||||
final CookieCsrfTokenRepository cookieCsrfTokenRepo = new CookieCsrfTokenRepository();
|
||||
//make secure true when using only https
|
||||
cookieCsrfTokenRepo.setCookieCustomizer(responseCookieBuilder -> responseCookieBuilder.secure(true));
|
||||
|
||||
// bellow line is used when you are using JWT tokens instead of jSession session keys but i put always because i guess CSRF token needs it
|
||||
http.
|
||||
logout((logout) -> logout.deleteCookies("Authorization", "JSESSIONID", "XSRF-TOKEN"))
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
|
||||
//now because we aare sending the JWT token to The UI Application in a Header
|
||||
//we need to manage it in the CORs config
|
||||
.cors(corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() {
|
||||
@Override
|
||||
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
|
||||
//check CORs and CSRF in Previous commits
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
// config.setAllowedOrigins(Collections.singletonList("http://localhost:4200"));
|
||||
config.setAllowedOrigins(Collections.singletonList("*"));
|
||||
config.setAllowedMethods(Collections.singletonList("*"));
|
||||
config.setAllowCredentials(true);
|
||||
config.setAllowedHeaders(Collections.singletonList("*"));
|
||||
//the JWT will be sent to UI under Authorization header and XSR under X-XSRF-TOKEN
|
||||
config.setExposedHeaders(List.of("Authorization", "X-XSRF-TOKEN"));
|
||||
config.setMaxAge(3600L);
|
||||
return config;
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
//temporarily disabling cross sight resource forgery
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
// .csrf((csrf) ->
|
||||
// csrf.csrfTokenRequestHandler(requestHandler).
|
||||
// ignoringRequestMatchers("/open/signup","/open/login","/user/getXSRfToken")
|
||||
// //.csrfTokenRepository(new CookieCsrfTokenRepository())
|
||||
// .csrfTokenRepository(cookieCsrfTokenRepo)
|
||||
// )
|
||||
//.addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class)
|
||||
|
||||
//token generation after BasicAuthenticationFilter.class
|
||||
.addFilterAfter(new JWTTokenGeneratorFilter(), BasicAuthenticationFilter.class)
|
||||
//then position the verification filter
|
||||
.addFilterBefore(new JWTTokenValidatorFilter(), BasicAuthenticationFilter.class)
|
||||
.authorizeHttpRequests((requests) -> requests
|
||||
//only admin can use this rout
|
||||
//user roles :- ROLE_admin ROLE_employee ROLE_manager ROLE_user
|
||||
.requestMatchers(
|
||||
"/cezen/add_user",
|
||||
"/cezen/add_feature",
|
||||
"/cezen/delete_extension",
|
||||
"/cezen/set_aors",
|
||||
"/cezen/set_password",
|
||||
"/cezen/add_extension"
|
||||
).hasAnyRole("admin")
|
||||
//any one who is authenticated can access /logout
|
||||
.requestMatchers("/open/login", "/user/getXSRfToken", "/logout").authenticated()
|
||||
//all the rest are open to public
|
||||
.requestMatchers("/open/signup").permitAll()
|
||||
//.requestMatchers(HttpMethod.POST, "/open/**").permitAll()
|
||||
)
|
||||
// redirect to /login if the user is not authenticated Customizer.withDefaults() enables a security feature using the defaults provided by Spring Security
|
||||
.formLogin(Customizer.withDefaults())
|
||||
.httpBasic(Customizer.withDefaults());
|
||||
|
||||
System.out.print("Security chain configured");
|
||||
return http.build();
|
||||
|
||||
}
|
||||
|
||||
// to encode the password
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.example.cezenPBX.config;
|
||||
|
||||
import com.example.cezenPBX.DAO.UserOpsDAO;
|
||||
import com.example.cezenPBX.entity.user.UserEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class CustomAuthenticationProviderForCezen implements AuthenticationProvider {
|
||||
|
||||
@Autowired
|
||||
private UserOpsDAO userOpsDAO;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
|
||||
//get credentials from login form
|
||||
String username = authentication.getName();
|
||||
String pwd = authentication.getCredentials().toString();
|
||||
|
||||
//sanity check
|
||||
if (username.isEmpty() || pwd.isEmpty()) return null;
|
||||
|
||||
//check for employee
|
||||
UserEntity user = null;
|
||||
try {
|
||||
//check if employee exists if yes then fetch details
|
||||
user = this.userOpsDAO.getUserByUserName(username);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (passwordEncoder.matches(pwd, user.getPassword())) {
|
||||
|
||||
//then it is a match a number of springs granted authorities
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
|
||||
//loop through the users authorities and add each of them to simple granted authority
|
||||
try {
|
||||
//check if user is part of permission set for admin signing in
|
||||
boolean isAdmin = false;
|
||||
for(var permission : user.getRoles()){
|
||||
if(permission.getRole().equals("ROLE_admin")) isAdmin = true;
|
||||
}
|
||||
if(!isAdmin) throw new BadCredentialsException("no employee permission for given employee");
|
||||
|
||||
user.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole())));
|
||||
} catch (Exception e) {
|
||||
//use/**/r doesn't have permissions or roles = null
|
||||
System.out.println(e.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(user.getUserName(), pwd, authorities);
|
||||
} else {
|
||||
throw new BadCredentialsException("Invalid password!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
//tells spring that i want to support username password style of auth
|
||||
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.example.cezenPBX.constents;
|
||||
|
||||
public interface SecurityConstants {
|
||||
|
||||
public static final String JWT_KEY = ";sdmn3426FHB426RH62389;]['/.sdwswa";
|
||||
public static final String JWT_HEADER = "Authorization";
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.example.cezenPBX.controller;
|
||||
|
||||
import com.example.cezenPBX.DTO.ReturnStatus;
|
||||
import com.example.cezenPBX.DTO.user.AdminSetPasswordDTO;
|
||||
import com.example.cezenPBX.service.PbxUserService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/open")
|
||||
public class SignUpController {
|
||||
|
||||
@Autowired
|
||||
private PbxUserService pbxUserService;
|
||||
|
||||
//sign up route
|
||||
@PostMapping("/signup")
|
||||
public ReturnStatus signUp(@RequestBody @Valid AdminSetPasswordDTO adminSetPasswordDTO){
|
||||
|
||||
return this.pbxUserService.adminSetUserNamePasswordSet(
|
||||
adminSetPasswordDTO.userName(),
|
||||
adminSetPasswordDTO.password(),
|
||||
adminSetPasswordDTO.confirmPassword(),
|
||||
adminSetPasswordDTO.email()
|
||||
);
|
||||
}
|
||||
|
||||
// and a login route
|
||||
@GetMapping("/login")
|
||||
public ReturnStatus login(){
|
||||
return new ReturnStatus(true, "Welcome user authenticated successfully", "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// forgot password
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.example.cezenPBX.entity.user;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Entity
|
||||
@Table(name = "roles")
|
||||
final public class Role {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "role_id")
|
||||
private int id;
|
||||
|
||||
//remember ROLE_
|
||||
@Column(name = "role_name")
|
||||
private String role;
|
||||
|
||||
//all employees under this role
|
||||
// map by may be required
|
||||
@ManyToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {
|
||||
//The detach operation removes the entity from the persistent context. When we use CascadeType.DETACH, the child entity will also get removed from the persistent context.
|
||||
CascadeType.DETACH,
|
||||
CascadeType.MERGE,
|
||||
CascadeType.PERSIST,
|
||||
CascadeType.REFRESH,
|
||||
}
|
||||
//cascade = CascadeType.ALL
|
||||
)
|
||||
@JoinTable(
|
||||
name = "user_roles",
|
||||
joinColumns = @JoinColumn(name = "role_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "u_id")
|
||||
)
|
||||
private Collection<UserEntity> employees;
|
||||
|
||||
public Role(){}
|
||||
|
||||
public Role(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public Collection<UserEntity> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public void setEmployees(Collection<UserEntity> employees) {
|
||||
this.employees = employees;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package com.example.cezenPBX.entity.user;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user")
|
||||
final public class UserEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "u_id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "user_name")
|
||||
private String userName;
|
||||
|
||||
@JsonIgnore
|
||||
@Column(name = "password")
|
||||
private String password;
|
||||
|
||||
@Column(name = "user_email_id")
|
||||
private String email;
|
||||
|
||||
//ROLE
|
||||
@ManyToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {
|
||||
//The detach operation removes the entity from the persistent context. When we use CascadeType.DETACH, the child entity will also get removed from the persistent context.
|
||||
CascadeType.DETACH,
|
||||
CascadeType.MERGE,
|
||||
CascadeType.PERSIST,
|
||||
CascadeType.REFRESH,
|
||||
}
|
||||
//cascade = CascadeType.ALL
|
||||
)
|
||||
@JoinTable(
|
||||
name = "user_roles",
|
||||
joinColumns = @JoinColumn(name = "u_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "role_id")
|
||||
)
|
||||
private Collection<Role> roles;
|
||||
|
||||
|
||||
public UserEntity(){}
|
||||
|
||||
public UserEntity(String userName, String password, String email) {
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
public Collection<Role> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public void setARole(Role role){
|
||||
if(this.roles == null){
|
||||
this.roles = new HashSet<Role>();
|
||||
}
|
||||
|
||||
this.roles.add(role);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.example.cezenPBX.security;
|
||||
|
||||
import com.example.cezenPBX.constents.SecurityConstants;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class JWTTokenGeneratorFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
//at this point the user is authenticated we just have to send the token back
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (null != authentication) {
|
||||
|
||||
//get the JWT key from the contents we defined
|
||||
// Keys, Jwts class comes from pom.xml
|
||||
SecretKey key = Keys.hmacShaKeyFor(SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
//creating a JWT token
|
||||
// issuer issues a jwt token
|
||||
//subject can be any value
|
||||
String jwt = Jwts.builder().issuer("Mathew Francis").subject("JWT_Token")
|
||||
//building the token
|
||||
.claim("username", authentication.getName())
|
||||
.claim("authorities", populateAuthorities(authentication.getAuthorities()))
|
||||
.issuedAt(new Date())
|
||||
.expiration(new Date((new Date()).getTime() + 30000000))
|
||||
//signing it with the key we set on line 35
|
||||
.signWith(key).compact();
|
||||
//SecurityConstants.JWT_HEADER, in the Constants SecurityConstants folder
|
||||
//response.setHeader(SecurityConstants.JWT_HEADER, jwt);
|
||||
//uncomment for cookie based saving
|
||||
Cookie cookie = new Cookie(SecurityConstants.JWT_HEADER,jwt);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setSecure(true);
|
||||
cookie.setPath("/");
|
||||
response.addCookie(cookie);
|
||||
System.out.println("JWT Generated");
|
||||
}
|
||||
System.out.println("Intercepted");
|
||||
|
||||
System.out.println(response.getHeader("X-XSRF-TOKEN"));
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
//only generate if the path is login
|
||||
//other words this method will return false for /login
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
|
||||
return !request.getServletPath().equals("/open/login");
|
||||
//return !(request.getServletPath().equals("/open/signup") || request.getServletPath().equals("/open/login"));
|
||||
}
|
||||
|
||||
// gets the authority's from granted authority which we set in the configuration CustomAuthenticationProvider class
|
||||
// plug in user auth into jwt token
|
||||
private String populateAuthorities(Collection<? extends GrantedAuthority> collection) {
|
||||
Set<String> authoritiesSet = new HashSet<>();
|
||||
for (GrantedAuthority authority : collection) {
|
||||
authoritiesSet.add(authority.getAuthority());
|
||||
}
|
||||
return String.join(",", authoritiesSet);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.example.cezenPBX.security;
|
||||
|
||||
import com.example.cezenPBX.constents.SecurityConstants;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class JWTTokenValidatorFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
// SecurityConstants
|
||||
// public static final String JWT_KEY = "jxgEQeXHuPq8VdbyYFNkANdudQ53YUn4";
|
||||
// public static final String JWT_HEADER = "Authorization";
|
||||
//String jwt = request.getHeader(SecurityConstants.JWT_HEADER);
|
||||
//below is the COOKIE approach
|
||||
String jwt = null;
|
||||
for(var cookie : request.getCookies()){
|
||||
if(cookie.getName().equals("Authorization")){
|
||||
System.out.print("COOKIE");
|
||||
System.out.println(cookie.getValue());
|
||||
jwt = cookie.getValue();
|
||||
}
|
||||
}
|
||||
if (null != jwt) {
|
||||
try {
|
||||
//generating the key
|
||||
SecretKey key = Keys.hmacShaKeyFor(
|
||||
SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
//verification of legitimacy
|
||||
Claims claims = Jwts.parser()
|
||||
.verifyWith(key)
|
||||
.build()
|
||||
.parseSignedClaims(jwt)
|
||||
.getPayload();
|
||||
String username = String.valueOf(claims.get("username"));
|
||||
String authorities = (String) claims.get("authorities");
|
||||
|
||||
// System.out.println("JWT name : "+ username);
|
||||
// System.out.println("JWT auth "+ authorities);
|
||||
|
||||
//if successful the result will be stored in SecurityContextHolder
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(username, null,
|
||||
//this comes in a string of comas and values
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(authorities));
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
} catch (Exception e) {
|
||||
throw new BadCredentialsException("Invalid Token received!");
|
||||
}
|
||||
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
//should be executed for all the api except the login api
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
|
||||
return request.getServletPath().equals("/open/signup")
|
||||
|| request.getServletPath().equals("/open/login");
|
||||
// //bellow was done to archive this /exposed/**
|
||||
// request.getServletPath().split("/")[1].equals("exposed");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.example.cezenPBX.service;
|
||||
|
||||
import com.example.cezenPBX.DAO.UserOpsDAO;
|
||||
import com.example.cezenPBX.DTO.ReturnStatus;
|
||||
import com.example.cezenPBX.entity.user.UserEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PbxUserService {
|
||||
|
||||
@Autowired
|
||||
private UserOpsDAO userOpsDAO;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
|
||||
// must perform the sanity checks before being set to the database
|
||||
// method will return a faulty return status if the damin exists
|
||||
public ReturnStatus adminSetUserNamePasswordSet(String userName, String password, String confirmPassword, String email){
|
||||
// password will be checked here
|
||||
if(!password.equals(confirmPassword)){
|
||||
return new ReturnStatus(false, "Passwords do not match", "Passwords do not match");
|
||||
}
|
||||
// password encryption
|
||||
UserEntity userEntity = new UserEntity(userName, passwordEncoder.encode(password), email);
|
||||
|
||||
// commit the username and password to the database
|
||||
return userOpsDAO.adminSetUsernameAndPassword(userEntity);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user