2023-03-21 19:03:06 +09:00
//-----------------------------------------------------------
2023-03-22 10:00:57 +09:00
// Search on Users and Machines pages
2023-03-21 19:03:06 +09:00
//-----------------------------------------------------------
2023-03-22 10:31:10 +09:00
function show _search ( ) {
$ ( '#nav-search' ) . removeClass ( 'hidden' ) ;
$ ( '#nav-search' ) . addClass ( 'show' ) ;
$ ( '#nav-content' ) . removeClass ( 'show' ) ;
$ ( '#nav-content' ) . addClass ( 'hidden' ) ;
}
2023-03-21 20:23:53 +09:00
2023-03-22 10:31:10 +09:00
function hide _search ( ) {
$ ( '#nav-content' ) . removeClass ( 'hidden' ) ;
$ ( '#nav-content' ) . addClass ( 'show' ) ;
$ ( '#nav-search' ) . removeClass ( 'show' ) ;
$ ( '#nav-search' ) . addClass ( 'hidden' ) ;
2023-03-22 12:42:16 +09:00
// Also remove the contents of the searchbox:
document . getElementById ( "search" ) . value = ""
2023-03-22 12:48:49 +09:00
let cards = document . querySelectorAll ( '.searchable' ) ;
for ( var i = 0 ; i < cards . length ; i ++ ) {
cards [ i ] . classList . remove ( "hide" ) ;
}
2023-03-22 10:31:10 +09:00
}
function liveSearch ( ) {
let cards = document . querySelectorAll ( '.searchable' ) ;
2023-03-22 11:36:27 +09:00
let search _query = document . getElementById ( "search" ) . value ;
2023-04-21 01:28:56 +08:00
2023-03-22 10:31:10 +09:00
for ( var i = 0 ; i < cards . length ; i ++ ) {
2023-04-21 01:28:56 +08:00
if ( cards [ i ] . textContent . toLowerCase ( ) . includes ( search _query . toLowerCase ( ) ) ) {
2023-03-22 10:31:10 +09:00
cards [ i ] . classList . remove ( "hide" ) ;
} else {
cards [ i ] . classList . add ( "hide" ) ;
2023-03-22 10:00:57 +09:00
}
}
2023-03-22 10:31:10 +09:00
}
2023-02-06 04:58:09 +00:00
//-----------------------------------------------------------
// General Helpers
//-----------------------------------------------------------
2023-04-21 01:28:56 +08:00
function loading ( ) {
2023-02-06 04:58:09 +00:00
return ` <center>
< div class = "preloader-wrapper big active" >
< div class = "spinner-layer spinner-blue-only" >
< div class = "circle-clipper left" >
< div class = "circle" >
< / d i v >
< / d i v >
< div class = "gap-patch" >
< div class = "circle" >
< / d i v >
< / d i v >
< div class = "circle-clipper right" >
< div class = "circle" > < / d i v >
< / d i v >
< / d i v >
< / d i v >
< / c e n t e r > `
}
function get _color ( id ) {
// Define the colors... Seems like a good number to start with
var colors = [
"red lighten-1" ,
"teal lighten-1" ,
"blue lighten-1" ,
"blue-grey lighten-1" ,
"indigo lighten-2" ,
"green lighten-1" ,
"deep-orange lighten-1" ,
"yellow lighten-2" ,
"purple lighten-2" ,
"indigo lighten-2" ,
"brown lighten-1" ,
"grey lighten-1"
] ;
index = id % colors . length
return colors [ index ]
}
// Generic modal used for alerts / problems
function load _modal _generic ( type , title , message ) {
console . log ( "Loading the generic modal" )
2023-04-21 01:28:56 +08:00
element = document . getElementById ( 'generic_modal' )
2023-02-06 04:58:09 +00:00
content _element = document . getElementById ( 'generic_modal_content' )
2023-04-21 01:28:56 +08:00
title _element = document . getElementById ( 'generic_modal_title' )
2023-02-06 04:58:09 +00:00
content _element . innerHTML = loading ( )
title _element . innerHTML = "Loading..."
html = ""
switch ( type ) {
case "warning" || "Warning" :
title _html = "Warning"
2023-04-21 01:28:56 +08:00
content _html = `
2023-02-06 04:58:09 +00:00
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle yellow" > priority _high < / i >
< span class = "title" > $ { title } < / s p a n >
< p > $ { message } < / p >
< / l i >
< / u l > `
break ;
case "success" || "Success" :
title _html = "Success"
2023-04-21 01:28:56 +08:00
content _html = `
2023-02-06 04:58:09 +00:00
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle green" > check < / i >
< span class = "title" > $ { title } < / s p a n >
< p > $ { message } < / p >
< / l i >
< / u l > `
break ;
2023-04-21 01:28:56 +08:00
case "error" || "Error" :
2023-02-06 04:58:09 +00:00
title _html = "Error"
2023-04-21 01:28:56 +08:00
content _html = `
2023-02-06 04:58:09 +00:00
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > $ { title } < / s p a n >
< p > $ { message } < / p >
< / l i >
< / u l > `
break ;
case "information" || "Information" :
title _html = "Information"
2023-04-21 01:28:56 +08:00
content _html = `
2023-02-06 04:58:09 +00:00
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle grey" > help < / i >
< span class = "title" > $ { title } < / s p a n >
< p > $ { message } < / p >
< / l i >
< / u l > `
break ;
}
title _element . innerHTML = title _html
content _element . innerHTML = content _html
var instance = M . Modal . getInstance ( element ) ;
instance . open ( )
}
2023-03-17 18:19:28 +09:00
// https://stackoverflow.com/questions/3043775/how-to-escape-html#22706073
2023-04-21 01:28:56 +08:00
function escapeHTML ( str ) {
2023-03-17 18:19:28 +09:00
var p = document . createElement ( "p" ) ;
p . appendChild ( document . createTextNode ( str ) ) ;
return p . innerHTML ;
}
2023-02-06 04:58:09 +00:00
// Enables the Floating Action Button (FAB) for the Machines and Users page
2023-04-21 01:28:56 +08:00
document . addEventListener ( 'DOMContentLoaded' , function ( ) {
2023-02-06 04:58:09 +00:00
var elems = document . querySelectorAll ( '.fixed-action-btn' ) ;
2023-04-21 01:28:56 +08:00
var instances = M . FloatingActionButton . init ( elems , { hoverEnabled : false } ) ;
2023-02-06 04:58:09 +00:00
} ) ;
// Init the date picker when adding PreAuth keys
2023-04-21 01:28:56 +08:00
document . addEventListener ( 'DOMContentLoaded' , function ( ) {
2023-02-06 04:58:09 +00:00
var elems = document . querySelectorAll ( '.datepicker' ) ;
var instances = M . Datepicker . init ( elems ) ;
} ) ;
//-----------------------------------------------------------
// Settings Page Actions
//-----------------------------------------------------------
function test _key ( ) {
document . getElementById ( 'test_modal_results' ) . innerHTML = loading ( )
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var api _key = document . getElementById ( 'api_key' ) . value ;
2023-02-06 04:58:09 +00:00
var data = $ . ajax ( {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/test_key" ,
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
data : JSON . stringify ( { "api_key" : api _key } ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
document . getElementById ( 'test_modal_results' ) . innerHTML = `
2023-02-06 04:58:09 +00:00
< ul class = "collection" >
< li class = "collection-item avatar" >
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
< i class = "material-icons circle green" > check < / i >
< span class = "title" > Success < / s p a n >
< p > Key authenticated with the Headscale server . < / p >
2023-02-06 04:58:09 +00:00
< / l i >
< / u l >
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
< h6 > Key Information < / h 6 >
< table class = "highlight" >
< tbody >
< tr >
< td > < b > Key ID < / b > < / t d >
< td > $ { response . id } < / t d >
< / t r >
< tr >
< td > < b > Prefix < / b > < / t d >
< td > $ { response . prefix } < / t d >
< / t r >
< tr >
< td > < b > Expiration Date < / b > < / t d >
< td > $ { response . expiration } < / t d >
< / t r >
< tr >
< td > < b > Creation Date < / b > < / t d >
< td > $ { response . createdAt } < / t d >
< / t r >
< / t b o d y >
< / t a b l e >
2023-02-06 04:58:09 +00:00
`
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
} ,
error : function ( xhr , textStatus , errorThrown ) {
document . getElementById ( 'test_modal_results' ) . innerHTML = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > Error < / s p a n >
< p > Key authentication failed . Check your key . < / p >
< / l i >
< / u l >
`
2023-02-06 04:58:09 +00:00
}
} )
}
function save _key ( ) {
var api _key = document . getElementById ( 'api_key' ) . value ;
if ( ! api _key ) {
html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > Error < / s p a n >
< p > You must enter an API key before saving . < / p >
< / l i >
< / u l >
`
document . getElementById ( 'test_modal_results' ) . innerHTML = html
return
} ;
2023-04-21 01:28:56 +08:00
var data = { "api_key" : api _key } ;
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/save_key" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
M . toast ( { html : 'Testing key and saving...' } ) ;
test _key ( ) ;
} ,
error : function ( xhr , textStatus , errorThrown ) {
M . toast ( { html : xhr . responseText } )
2023-02-06 04:58:09 +00:00
test _key ( ) ;
}
} )
}
//-----------------------------------------------------------
// Modal Loaders
//-----------------------------------------------------------
function load _modal _rename _user ( user _id , old _name ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "green btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Rename"
2023-04-21 01:28:56 +08:00
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Rename user '" + old _name + "'?"
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle" > language < / i >
< span class = "title" > Information < / s p a n >
< p > You are about to rename the user '${old_name}' < / p >
< / l i >
< / u l >
< h6 > New Name < / h 6 >
< div class = "input-field" >
< i class = "material-icons prefix" > language < / i >
< input value = '${old_name}' id = "new_user_name_form" type = "text" data - length = "32" >
< / d i v >
`
modal _body . innerHTML = body _html
2023-04-21 01:28:56 +08:00
$ ( document ) . ready ( function ( ) { $ ( 'input#new_user_name_form' ) . characterCounter ( ) ; } ) ;
2023-02-06 04:58:09 +00:00
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'rename_user(' + user _id + ', "' + old _name + '")' )
2023-02-06 04:58:09 +00:00
}
function load _modal _delete _user ( user _id , user _name ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "red btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Delete"
2023-04-21 01:28:56 +08:00
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Delete user '" + user _name + "'?"
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > Warning < / s p a n >
< p > Are you sure you want to delete the user '${user_name}' ? < / p >
< / l i >
< / u l >
`
modal _body . innerHTML = body _html
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'delete_user("' + user _id + '", "' + user _name + '")' )
2023-02-06 04:58:09 +00:00
}
function load _modal _add _preauth _key ( user _name ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "green btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Add"
2023-04-21 01:28:56 +08:00
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Adding a PreAuth key to '" + user _name + "'"
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle" > help < / i >
< span class = "title" > Information < / s p a n >
< p >
< ul >
< li > Pre - Auth keys can be used to authenticate to Headscale without manually registering a machine . Use the flag < code > -- auth - key < / c o d e > t o d o s o . < / l i >
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
< li > "Ephemeral" keys can be used to register devices that frequently come on and drop off the network ( for example , docker containers ) < / l i >
< li > Keys that are "Reusable" can be used multiple times . Keys that are "One Time Use" will expire after their first use . < / l i >
2023-02-06 04:58:09 +00:00
< / u l >
< / p >
< / l i >
< / u l >
< h4 > PreAuth Key Information < / h 4 >
< br >
2023-02-28 21:36:02 +09:00
< input type = "text" class = "datepicker" id = "preauth_key_expiration_date" >
2023-02-06 04:58:09 +00:00
< p >
< label >
< input type = "checkbox" class = "filled-in" id = "checkbox-reusable" / >
< span > Reusable < / s p a n >
< / l a b e l >
< / p >
< p >
< label >
< input type = "checkbox" class = "filled-in" id = "checkbox-ephemeral" / >
< span > Ephemeral < / s p a n >
< / l a b e l >
< / p >
`
modal _body . innerHTML = body _html
// Init the date picker
2023-04-21 01:28:56 +08:00
M . Datepicker . init ( document . querySelector ( '.datepicker' ) , { format : 'yyyy-mm-dd' } ) ;
2023-02-06 04:58:09 +00:00
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'add_preauth_key("' + user _name + '")' )
2023-02-06 04:58:09 +00:00
}
function load _modal _expire _preauth _key ( user _name , key ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "red lighten-2 btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Expire"
2023-04-21 01:28:56 +08:00
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
modal _title . innerHTML = "Expire PreAuth Key?"
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > Warning < / s p a n >
< p > Are you sure you want to expire this key ? It will become unusable afterwards , and any machine currently using it will disconnect . < / p >
< / l i >
< / u l >
`
modal _body . innerHTML = body _html
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'expire_preauth_key("' + user _name + '", "' + key + '")' )
2023-02-06 04:58:09 +00:00
}
function load _modal _move _machine ( machine _id ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "green btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Move"
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/machine_information" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( headscale ) {
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/get_users" ,
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
data : "{}" ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Move machine '" + headscale . machine . givenName + "'?"
2023-02-06 04:58:09 +00:00
select _html = ` <h6>Select a User</h6><select id='move-select'> `
2023-04-21 01:28:56 +08:00
for ( let i = 0 ; i < response . users . length ; i ++ ) {
2023-02-06 04:58:09 +00:00
var name = response [ "users" ] [ i ] [ "name" ]
2023-04-21 01:28:56 +08:00
select _html = select _html + ` <option value=" ${ name } "> ${ name } </option> `
2023-02-06 04:58:09 +00:00
}
2023-04-21 01:28:56 +08:00
select _html = select _html + ` </select> `
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle" > language < / i >
< span class = "title" > Information < / s p a n >
< p > You are about to move $ { headscale . machine . givenName } to a new user . < / p >
< / l i >
< / u l > `
2023-04-21 01:28:56 +08:00
body _html = body _html + select _html
body _html = body _html + ` <h6>Machine Information</h6>
2023-02-06 04:58:09 +00:00
< table class = "highlight" >
< tbody >
< tr >
< td > < b > Machine ID < / b > < / t d >
< td > $ { headscale . machine . id } < / t d >
< / t r >
< tr >
< td > < b > Hostname < / b > < / t d >
< td > $ { headscale . machine . name } < / t d >
< / t r >
< tr >
< td > < b > User < / b > < / t d >
< td > $ { headscale . machine . user . name } < / t d >
< / t r >
< / t b o d y >
< / t a b l e >
`
modal _body . innerHTML = body _html
M . FormSelect . init ( document . querySelectorAll ( 'select' ) )
}
} )
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'move_machine(' + machine _id + ')' )
2023-02-06 04:58:09 +00:00
}
} )
}
function load _modal _delete _machine ( machine _id ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "red btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Delete"
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/machine_information" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Delete machine '" + response . machine . givenName + "'?"
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle red" > warning < / i >
< span class = "title" > Warning < / s p a n >
< p > Are you sure you want to delete $ { response . machine . givenName } ? < / p >
< / l i >
< / u l >
< h6 > Machine Information < / h 6 >
< table class = "highlight" >
< tbody >
< tr >
< td > < b > Machine ID < / b > < / t d >
< td > $ { response . machine . id } < / t d >
< / t r >
< tr >
< td > < b > Hostname < / b > < / t d >
< td > $ { response . machine . name } < / t d >
< / t r >
< tr >
< td > < b > User < / b > < / t d >
< td > $ { response . machine . user . name } < / t d >
< / t r >
< / t b o d y >
< / t a b l e >
`
modal _body . innerHTML = body _html
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'delete_machine(' + machine _id + ')' )
2023-02-06 04:58:09 +00:00
}
} )
}
function load _modal _rename _machine ( machine _id ) {
document . getElementById ( 'modal_content' ) . innerHTML = loading ( )
document . getElementById ( 'modal_title' ) . innerHTML = "Loading..."
document . getElementById ( 'modal_confirm' ) . className = "green btn-flat white-text"
document . getElementById ( 'modal_confirm' ) . innerText = "Rename"
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/machine_information" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
modal = document . getElementById ( 'card_modal' ) ;
modal _title = document . getElementById ( 'modal_title' ) ;
modal _body = document . getElementById ( 'modal_content' ) ;
2023-02-06 04:58:09 +00:00
modal _confirm = document . getElementById ( 'modal_confirm' ) ;
2023-04-21 01:28:56 +08:00
modal _title . innerHTML = "Rename machine '" + response . machine . givenName + "'?"
2023-02-06 04:58:09 +00:00
body _html = `
< ul class = "collection" >
< li class = "collection-item avatar" >
< i class = "material-icons circle" > devices < / i >
< span class = "title" > Information < / s p a n >
< p > You are about to rename $ { response . machine . givenName } < / p >
< / l i >
< / u l >
< h6 > New Name < / h 6 >
< div class = "input-field" >
< input value = '${response.machine.givenName}' id = "new_name_form" type = "text" >
< label for = "new_name_form" class = "active" > New Machine Name < / l a b e l >
< / d i v >
< h6 > Machine Information < / h 6 >
< table class = "highlight" >
< tbody >
< tr >
< td > < b > Machine ID < / b > < / t d >
< td > $ { response . machine . id } < / t d >
< / t r >
< tr >
< td > < b > Hostname < / b > < / t d >
< td > $ { response . machine . name } < / t d >
< / t r >
< tr >
< td > < b > User < / b > < / t d >
< td > $ { response . machine . user . name } < / t d >
< / t r >
< / t b o d y >
< / t a b l e >
`
modal _body . innerHTML = body _html
2023-04-21 01:28:56 +08:00
modal _confirm . setAttribute ( 'onclick' , 'rename_machine(' + machine _id + ')' )
2023-02-06 04:58:09 +00:00
}
} )
}
function load _modal _add _machine ( ) {
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/get_users" ,
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
data : "{}" ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-02-06 04:58:09 +00:00
modal _body = document . getElementById ( 'default_add_new_machine_modal' ) ;
modal _confirm = document . getElementById ( 'new_machine_modal_confirm' ) ;
select _html = `
< div class = "col s12 m6" >
< div class = "input-field" >
< i class = "material-icons prefix" > language < / i >
< select id = 'add_machine_user_select' >
< option value = "" disabled selected > Select a User < / o p t i o n > `
2023-04-21 01:28:56 +08:00
for ( let i = 0 ; i < response . users . length ; i ++ ) {
2023-02-06 04:58:09 +00:00
var name = response [ "users" ] [ i ] [ "name" ]
2023-04-21 01:28:56 +08:00
select _html = select _html + ` <option value=" ${ name } "> ${ name } </option> `
2023-02-06 04:58:09 +00:00
}
select _html = select _html + `
< label > Select a User < / l a b e l >
< / s e l e c t >
< / d i v >
< / d i v > `
select _html = select _html + `
< div class = "col s12 m6" >
< div class = "input-field" >
< i class = "material-icons prefix" > vpn _key < / i >
< input id = "add_machine_key_field" type = "password" >
< label for = "add_machine_key_field" > Machine Registration Key < / l a b e l >
< / d i v >
< / d i v > `
2023-04-21 01:28:56 +08:00
for ( let i = 0 ; i < response . users . length ; i ++ ) {
2023-02-06 04:58:09 +00:00
var name = response [ "users" ] [ i ] [ "name" ]
}
modal _body . innerHTML = select _html
// Initialize the form and the machine tabs
2023-04-21 01:28:56 +08:00
M . FormSelect . init ( document . querySelectorAll ( 'select' ) , { classes : 'add_machine_selector_class' } )
2023-02-06 04:58:09 +00:00
M . Tabs . init ( document . getElementById ( 'new_machine_tabs' ) ) ;
}
} )
}
//-----------------------------------------------------------
// Machine Page Actions
//-----------------------------------------------------------
function delete _chip ( machine _id , chipsData ) {
// We need to get ALL the current tags -- We don't care about what's deleted, just what's remaining
// chipsData is an array generated from from the creation of the array.
chips = JSON . stringify ( chipsData )
var formattedData = [ ] ;
for ( let tag in chipsData ) {
2023-04-21 01:28:56 +08:00
formattedData [ tag ] = '"tag:' + chipsData [ tag ] . tag + '"'
2023-02-06 04:58:09 +00:00
}
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id , "tags" : formattedData }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/set_machine_tags" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
M . toast ( { html : 'Tag removed.' } ) ;
2023-02-06 04:58:09 +00:00
}
} )
}
function add _chip ( machine _id , chipsData ) {
chips = JSON . stringify ( chipsData ) . toLowerCase ( )
chipsData [ chipsData . length - 1 ] . tag = chipsData [ chipsData . length - 1 ] . tag . trim ( ) . replace ( /\s+/g , '-' )
last _chip _fixed = chipsData [ chipsData . length - 1 ] . tag
var formattedData = [ ] ;
for ( let tag in chipsData ) {
2023-04-21 01:28:56 +08:00
formattedData [ tag ] = '"tag:' + chipsData [ tag ] . tag + '"'
2023-02-06 04:58:09 +00:00
}
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id , "tags" : formattedData }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/set_machine_tags" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
M . toast ( { html : 'Tag "' + last _chip _fixed + '" added.' } ) ;
2023-02-06 04:58:09 +00:00
}
} )
}
function add _machine ( ) {
2023-04-21 01:28:56 +08:00
var key = document . getElementById ( 'add_machine_key_field' ) . value
2023-02-06 04:58:09 +00:00
var user = document . getElementById ( 'add_machine_user_select' ) . value
2023-04-21 01:28:56 +08:00
var data = { "key" : key , "user" : user }
2023-02-06 04:58:09 +00:00
if ( user == "" ) {
load _modal _generic ( "error" , "User is empty" , "Select a user before submitting" )
return
}
if ( key == "" ) {
load _modal _generic ( "error" , "Key is empty" , "Input the key generated by your <code>tailscale login</code> command" )
return
}
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/register_machine" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
window . location . reload ( )
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error adding machine" , JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function rename _machine ( machine _id ) {
var new _name = document . getElementById ( 'new_name_form' ) . value ;
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id , "new_name" : new _name } ;
2023-02-06 04:58:09 +00:00
// String to test against
2023-04-21 01:28:56 +08:00
var regexIT = /[`!@#$%^&*()_+\=\[\]{};':"\\|,.<>\/?~]/ ;
if ( regexIT . test ( new _name ) ) { load _modal _generic ( "error" , "Invalid Name" , "Name cannot contain special characters ('" + regexIT + "')" ) ; return }
2023-02-06 04:58:09 +00:00
// If there are characters other than - and alphanumeric, throw an error
2023-04-21 01:28:56 +08:00
if ( new _name . includes ( ' ' ) ) { load _modal _generic ( "error" , "Name cannot have spaces" , "Allowed characters are dashes (-) and alphanumeric characters" ) ; return }
2023-02-06 04:58:09 +00:00
// If it is longer than 32 characters, throw an error
if ( new _name . length > 32 ) { load _modal _generic ( "error" , "Name is too long" , "The name name is too long. Maximum length is 32 characters" ) ; return }
// If the new_name is empty, throw an error
2023-04-21 01:28:56 +08:00
if ( ! new _name ) { load _modal _generic ( "error" , "Name can't be empty" , "Please enter a machine name before submitting." ) ; return }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/rename_machine" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
2023-02-06 04:58:09 +00:00
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
document . getElementById ( machine _id + '-name-container' ) . innerHTML = machine _id + ". " + escapeHTML ( new _name )
M . toast ( { html : 'Machine ' + machine _id + ' renamed to ' + escapeHTML ( new _name ) } ) ;
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error setting the machine name" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function move _machine ( machine _id ) {
new _user = document . getElementById ( 'move-select' ) . value
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id , "user" : new _user } ;
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/move_user" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-02-06 04:58:09 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
2023-04-21 01:28:56 +08:00
document . getElementById ( machine _id + '-user-container' ) . innerHTML = response . machine . user . name
document . getElementById ( machine _id + '-ns-badge' ) . innerHTML = response . machine . user . name
2023-02-06 04:58:09 +00:00
// Get the color and set it
var user _color = get _color ( response . machine . user . id )
2023-04-21 01:28:56 +08:00
document . getElementById ( machine _id + '-ns-badge' ) . className = "badge ipinfo " + user _color + " white-text hide-on-small-only"
2023-02-06 04:58:09 +00:00
2023-04-21 01:28:56 +08:00
M . toast ( { html : "'" + response . machine . givenName + "' moved to user " + response . machine . user . name } ) ;
2023-02-06 04:58:09 +00:00
}
} )
}
function delete _machine ( machine _id ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "machine_id" : machine _id } ;
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/delete_machine" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-02-06 04:58:09 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
// When the machine is deleted, hide its collapsible:
2023-04-21 01:28:56 +08:00
document . getElementById ( machine _id + '-main-collapsible' ) . className = "collapsible popout hide" ;
2023-02-06 04:58:09 +00:00
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'Machine deleted.' } ) ;
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error deleting machine" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
2023-03-24 14:12:21 +09:00
function toggle _exit ( route1 , route2 , exit _id , current _state , page ) {
2023-04-21 01:28:56 +08:00
var data1 = { "route_id" : route1 , "current_state" : current _state }
var data2 = { "route_id" : route2 , "current_state" : current _state }
2023-03-24 14:12:21 +09:00
var element = document . getElementById ( exit _id ) ;
var disabledClass = ""
2023-04-21 01:28:56 +08:00
var enabledClass = ""
2023-03-24 14:12:21 +09:00
if ( page == "machines" ) {
disabledClass = "waves-effect waves-light btn-small red lighten-2 tooltipped" ;
2023-04-21 01:28:56 +08:00
enabledClass = "waves-effect waves-light btn-small green lighten-2 tooltipped" ;
2023-03-24 14:12:21 +09:00
}
if ( page == "routes" ) {
disabledClass = "material-icons red-text text-lighten-2 tooltipped" ;
2023-04-21 01:28:56 +08:00
enabledClass = "material-icons green-text text-lighten-2 tooltipped" ;
2023-03-24 14:12:21 +09:00
}
var disabledTooltip = "Click to enable"
2023-04-21 01:28:56 +08:00
var enabledTooltip = "Click to disable"
var disableState = "False"
var enableState = "True"
var action _taken = "unchanged." ;
2023-03-24 14:12:21 +09:00
2023-03-22 14:31:30 +09:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-22 14:31:30 +09:00
url : "api/update_route" ,
data : JSON . stringify ( data1 ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-03-22 14:31:30 +09:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-22 14:31:30 +09:00
url : "api/update_route" ,
data : JSON . stringify ( data2 ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-03-22 14:31:30 +09:00
// Response is a JSON object containing the Headscale API response of /v1/api/machines/<id>/route
if ( element . className == disabledClass ) {
2023-04-21 01:28:56 +08:00
element . className = enabledClass
action _taken = "enabled."
2023-03-22 14:31:30 +09:00
element . setAttribute ( 'data-tooltip' , enabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_exit(' + route1 + ', ' + route2 + ', "' + exit _id + '", "' + enableState + '", "' + page + '")' )
2023-03-22 14:31:30 +09:00
} else if ( element . className == enabledClass ) {
2023-04-21 01:28:56 +08:00
element . className = disabledClass
action _taken = "disabled."
2023-03-22 14:31:30 +09:00
element . setAttribute ( 'data-tooltip' , disabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_exit(' + route1 + ', ' + route2 + ', "' + exit _id + '", "' + disableState + '", "' + page + '")' )
2023-03-22 14:31:30 +09:00
}
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'Exit Route ' + action _taken } ) ;
2023-03-22 14:31:30 +09:00
}
} )
}
} )
2023-03-22 13:58:51 +09:00
}
2023-03-24 12:10:38 +09:00
function toggle _route ( route _id , current _state , page ) {
2023-04-21 01:28:56 +08:00
var data = { "route_id" : route _id , "current_state" : current _state }
2023-03-24 11:49:49 +09:00
var element = document . getElementById ( route _id ) ;
2023-03-24 12:53:11 +09:00
2023-03-24 12:18:04 +09:00
var disabledClass = ""
2023-04-21 01:28:56 +08:00
var enabledClass = ""
2023-03-24 12:18:04 +09:00
2023-03-24 12:24:15 +09:00
if ( page == "machines" ) {
2023-03-24 13:02:32 +09:00
disabledClass = "waves-effect waves-light btn-small red lighten-2 tooltipped" ;
2023-04-21 01:28:56 +08:00
enabledClass = "waves-effect waves-light btn-small green lighten-2 tooltipped" ;
2023-03-24 13:02:32 +09:00
}
if ( page == "routes" ) {
2023-03-24 12:53:11 +09:00
disabledClass = "material-icons red-text text-lighten-2 tooltipped" ;
2023-04-21 01:28:56 +08:00
enabledClass = "material-icons green-text text-lighten-2 tooltipped" ;
2023-03-24 11:48:12 +09:00
}
2023-03-24 12:53:11 +09:00
2023-03-24 11:48:12 +09:00
var disabledTooltip = "Click to enable"
2023-04-21 01:28:56 +08:00
var enabledTooltip = "Click to disable"
var disableState = "False"
var enableState = "True"
var action _taken = "unchanged." ;
2023-03-24 08:16:44 +09:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-24 08:16:44 +09:00
url : "api/update_route" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-03-24 08:16:44 +09:00
if ( element . className == disabledClass ) {
2023-03-24 11:48:12 +09:00
element . className = enabledClass
2023-04-21 01:28:56 +08:00
action _taken = "enabled."
2023-03-24 08:16:44 +09:00
element . setAttribute ( 'data-tooltip' , enabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_route(' + route _id + ', "' + enableState + '", "' + page + '")' )
2023-03-24 08:16:44 +09:00
} else if ( element . className == enabledClass ) {
2023-03-24 11:48:12 +09:00
element . className = disabledClass
2023-04-21 01:28:56 +08:00
action _taken = "disabled."
2023-03-24 08:16:44 +09:00
element . setAttribute ( 'data-tooltip' , disabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_route(' + route _id + ', "' + disableState + '", "' + page + '")' )
2023-03-24 08:16:44 +09:00
}
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'Route ' + action _taken } ) ;
2023-03-24 08:16:44 +09:00
}
} )
}
2023-03-24 11:48:12 +09:00
2023-03-29 13:59:34 +09:00
function get _routes ( ) {
2023-03-30 10:01:49 +09:00
console . log ( "Getting info for all routes" )
2023-03-30 11:38:53 +09:00
var data
2023-03-29 13:59:34 +09:00
$ . ajax ( {
2023-03-30 11:26:10 +09:00
async : false ,
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-29 13:59:34 +09:00
url : "api/get_routes" ,
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
data : "{}" ,
2023-03-29 13:59:34 +09:00
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-03-30 11:09:04 +09:00
console . log ( "Got all routes." )
2023-03-30 11:38:53 +09:00
data = response
2023-03-29 13:59:34 +09:00
}
} )
2023-03-30 11:38:53 +09:00
return data
2023-03-29 13:59:34 +09:00
}
2023-03-30 09:47:27 +09:00
function toggle _failover _route _routespage ( routeid , current _state , prefix , route _id _list ) {
2023-03-29 13:59:34 +09:00
// First, toggle the route:
2023-03-29 17:58:52 +09:00
// toggle_route(route_id, current_state, page)
2023-04-21 01:28:56 +08:00
var data = { "route_id" : routeid , "current_state" : current _state }
console . log ( "Data: " + JSON . stringify ( data ) )
console . log ( "Passed in: " + routeid + ", " + current _state + ", " + prefix + ", " + route _id _list )
2023-03-30 09:47:27 +09:00
var element = document . getElementById ( routeid ) ;
2023-03-29 17:58:52 +09:00
var disabledClass = "material-icons red-text text-lighten-2 tooltipped" ;
2023-04-21 01:28:56 +08:00
var enabledClass = "material-icons green-text text-lighten-2 tooltipped" ;
2023-03-30 13:01:59 +09:00
var failover _disabledClass = "material-icons small left red-text text-lighten-2"
2023-04-21 01:28:56 +08:00
var failover _enabledClass = "material-icons small left green-text text-lighten-2"
2023-03-29 17:58:52 +09:00
var disabledTooltip = "Click to enable"
2023-04-21 01:28:56 +08:00
var enabledTooltip = "Click to disable"
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var disableState = false
var enableState = true
2023-04-21 01:28:56 +08:00
var action _taken = "unchanged."
2023-03-30 10:00:20 +09:00
2023-03-29 17:58:52 +09:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-29 17:58:52 +09:00
url : "api/update_route" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
console . log ( "Success: Route ID: " + routeid )
console . log ( "Success: route_id_list: " + route _id _list )
2023-03-29 17:58:52 +09:00
if ( element . className == disabledClass ) {
element . className = enabledClass
2023-04-21 01:28:56 +08:00
action _taken = "enabled."
2023-03-29 17:58:52 +09:00
element . setAttribute ( 'data-tooltip' , enabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_failover_route_routespage(' + routeid + ', "' + enableState + '", "' + prefix + '", [' + route _id _list + '])' )
2023-03-29 17:58:52 +09:00
} else if ( element . className == enabledClass ) {
element . className = disabledClass
2023-04-21 01:28:56 +08:00
action _taken = "disabled."
2023-03-29 17:58:52 +09:00
element . setAttribute ( 'data-tooltip' , disabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_failover_route_routespage(' + routeid + ', "' + disableState + '", "' + prefix + '", [' + route _id _list + '])' )
2023-03-29 17:58:52 +09:00
}
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'Route ' + action _taken } ) ;
2023-03-29 17:58:52 +09:00
2023-03-30 10:38:40 +09:00
// Get all route info:
2023-04-21 01:28:56 +08:00
console . log ( "Getting info for prefix " + prefix )
2023-03-29 17:58:52 +09:00
var routes = get _routes ( )
2023-03-30 13:20:18 +09:00
var failover _enabled = false
2023-03-30 10:38:40 +09:00
// Get the primary and enabled displays for the prefix:
2023-04-21 01:28:56 +08:00
for ( let i = 0 ; i < route _id _list . length ; i ++ ) {
console . log ( "route_id_list[" + i + "]: " + route _id _list [ i ] )
2023-03-30 12:33:37 +09:00
var route _id = route _id _list [ i ]
2023-04-21 01:28:56 +08:00
var route _index = route _id - 1
console . log ( "Looking for route " + route _id + " at index " + route _index )
console . log ( "isPrimary: " + routes [ "routes" ] [ route _index ] [ "isPrimary" ] )
2023-03-30 12:33:37 +09:00
2023-03-30 10:38:40 +09:00
// Set the Primary class:
2023-04-21 01:28:56 +08:00
var primary _element = document . getElementById ( route _id + "-primary" )
var primary _status = routes [ "routes" ] [ route _index ] [ "isPrimary" ]
var enabled _status = routes [ "routes" ] [ route _index ] [ "enabled" ]
2023-03-30 12:33:37 +09:00
2023-04-21 01:28:56 +08:00
console . log ( "enabled_status: " + enabled _status )
2023-03-30 13:01:59 +09:00
2023-03-30 12:57:35 +09:00
if ( enabled _status == true ) {
2023-03-30 13:13:26 +09:00
failover _enabled = true
2023-03-30 12:57:35 +09:00
}
2023-04-21 01:28:56 +08:00
console . log ( "Setting primary class '" + route _id + "-primary': " + primary _status )
2023-03-30 12:03:55 +09:00
if ( primary _status == true ) {
2023-03-30 10:48:41 +09:00
console . log ( "Detected this route is primary. Setting the class" )
2023-03-30 10:38:40 +09:00
primary _element . className = enabledClass
2023-03-30 12:03:55 +09:00
} else if ( primary _status == false ) {
2023-03-30 10:48:41 +09:00
console . log ( "Detected this route is NOT primary. Setting the class" )
2023-03-30 10:38:40 +09:00
primary _element . className = disabledClass
}
2023-03-30 12:57:35 +09:00
}
// if any route is enabled, set the prefix enable icon to enabled:
var failover _element = document . getElementById ( prefix )
2023-04-21 01:28:56 +08:00
console . log ( "Failover enabled: " + failover _enabled )
2023-03-30 12:57:35 +09:00
if ( failover _enabled == true ) {
2023-03-30 13:01:59 +09:00
failover _element . className = failover _enabledClass
2023-03-30 12:57:35 +09:00
}
else if ( failover _enabled == false ) {
2023-03-30 13:01:59 +09:00
failover _element . className = failover _disabledClass
2023-03-29 17:58:52 +09:00
}
}
} )
}
2023-03-29 13:59:34 +09:00
2023-03-22 21:07:22 +09:00
function toggle _failover _route ( route _id , current _state , color ) {
2023-04-21 01:28:56 +08:00
var data = { "route_id" : route _id , "current_state" : current _state }
2023-03-22 21:07:22 +09:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-03-22 21:07:22 +09:00
url : "api/update_route" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
2023-03-22 21:07:22 +09:00
// Response is a JSON object containing the Headscale API response of /v1/api/machines/<id>/route
2023-04-21 01:28:56 +08:00
var element = document . getElementById ( route _id ) ;
var disabledClass = "waves-effect waves-light btn-small red lighten-2 tooltipped" ;
var enabledClass = "waves-effect waves-light btn-small " + color + " lighten-2 tooltipped" ;
2023-03-22 22:07:12 +09:00
var disabledTooltip = "Click to enable (Failover Pair)"
2023-04-21 01:28:56 +08:00
var enabledTooltip = "Click to disable (Failover Pair)"
var disableState = "False"
var enableState = "True"
var action _taken = "unchanged." ;
2023-02-06 04:58:09 +00:00
if ( element . className == disabledClass ) {
// 1. Change the class to change the color of the icon
// 2. Change the "action taken" for the M.toast popup
// 3. Change the tooltip to say "Click to enable/disable"
2023-04-21 01:28:56 +08:00
element . className = enabledClass
var action _taken = "enabled."
2023-02-06 04:58:09 +00:00
element . setAttribute ( 'data-tooltip' , enabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_failover_route(' + route _id + ', "' + enableState + '", "' + color + '")' )
2023-02-06 04:58:09 +00:00
} else if ( element . className == enabledClass ) {
2023-04-21 01:28:56 +08:00
element . className = disabledClass
var action _taken = "disabled."
2023-02-06 04:58:09 +00:00
element . setAttribute ( 'data-tooltip' , disabledTooltip )
2023-04-21 01:28:56 +08:00
element . setAttribute ( 'onclick' , 'toggle_failover_route(' + route _id + ', "' + disableState + '", "' + color + '")' )
2023-02-06 04:58:09 +00:00
}
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'Route ' + action _taken } ) ;
2023-02-06 04:58:09 +00:00
}
} )
}
//-----------------------------------------------------------
// Machine Page Helpers
//-----------------------------------------------------------
function btn _toggle ( state ) {
2023-04-21 01:28:56 +08:00
if ( state == "show" ) { document . getElementById ( 'new_machine_modal_confirm' ) . className = 'green btn-flat white-text' }
else { document . getElementById ( 'new_machine_modal_confirm' ) . className = 'green btn-flat white-text hide' }
2023-02-06 04:58:09 +00:00
}
//-----------------------------------------------------------
// User Page Actions
//-----------------------------------------------------------
function rename _user ( user _id , old _name ) {
var new _name = document . getElementById ( 'new_user_name_form' ) . value ;
2023-04-21 01:28:56 +08:00
var data = { "old_name" : old _name , "new_name" : new _name }
2023-02-06 04:58:09 +00:00
// String to test against
2023-04-21 01:28:56 +08:00
var regexIT = /[`!@#$%^&*()_+\=\[\]{};':"\\|,.<>\/?~]/ ;
if ( regexIT . test ( new _name ) ) { load _modal _generic ( "error" , "Invalid Name" , "Name cannot contain special characters ('" + regexIT + "')" ) ; return }
2023-02-06 04:58:09 +00:00
// If there are characters other than - and alphanumeric, throw an error
2023-04-21 01:28:56 +08:00
if ( new _name . includes ( ' ' ) ) { load _modal _generic ( "error" , "Name cannot have spaces" , "Allowed characters are dashes (-) and alphanumeric characters" ) ; return }
2023-02-06 04:58:09 +00:00
// If it is longer than 32 characters, throw an error
if ( new _name . length > 32 ) { load _modal _generic ( "error" , "Name is too long" , "The user name is too long. Maximum length is 32 characters" ) ; return }
// If the new_name is empty, throw an error
2023-04-21 01:28:56 +08:00
if ( ! new _name ) { load _modal _generic ( "error" , "Name can't be empty" , "The user name cannot be empty." ) ; return }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/rename_user" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
// Rename the user on the page:
document . getElementById ( user _id + '-name-span' ) . innerHTML = escapeHTML ( new _name )
// Set the button to use the NEW name as the OLD name for both buttons
var rename _button _sm = document . getElementById ( user _id + '-rename-user-sm' )
rename _button _sm . setAttribute ( 'onclick' , 'load_modal_rename_user(' + user _id + ', "' + new _name + '")' )
var rename _button _lg = document . getElementById ( user _id + '-rename-user-lg' )
rename _button _lg . setAttribute ( 'onclick' , 'load_modal_rename_user(' + user _id + ', "' + new _name + '")' )
// Send the completion toast
M . toast ( { html : "User '" + old _name + "' renamed to '" + new _name + "'." } )
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error setting user name" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function delete _user ( user _id , user _name ) {
2023-04-21 01:28:56 +08:00
var data = { "name" : user _name } ;
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/delete_user" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
// When the machine is deleted, hide its collapsible:
document . getElementById ( user _id + '-main-collapsible' ) . className = "collapsible popout hide" ;
M . toast ( { html : 'User deleted.' } ) ;
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error deleting user" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function add _user ( ) {
var user _name = document . getElementById ( 'add_user_name_field' ) . value
2023-04-21 01:28:56 +08:00
var data = { "name" : user _name }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/add_user" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
// Send the completion toast
M . toast ( { html : "User '" + user _name + "' added to Headscale. Refreshing..." } )
window . location . reload ( )
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error adding user" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function add _preauth _key ( user _name ) {
2023-04-21 01:28:56 +08:00
var date = document . getElementById ( 'preauth_key_expiration_date' ) . value
var ephemeral = document . getElementById ( 'checkbox-ephemeral' ) . checked
var reusable = document . getElementById ( 'checkbox-reusable' ) . checked
var expiration = date + "T00:00:00.000Z" // Headscale format.
2023-02-06 04:58:09 +00:00
// If there is no date, error:
2023-04-21 01:28:56 +08:00
if ( ! date ) { load _modal _generic ( "error" , "Invalid Date" , "Please enter a valid date" ) ; return }
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
var data = { "user" : user _name , "reusable" : reusable , "ephemeral" : ephemeral , "expiration" : expiration , "acl_tags" : [ ] }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/add_preauth_key" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Send the completion toast
M . toast ( { html : 'PreAuth key created in user ' + user _name } )
// If this is successful, we should reload the table and close the modal:
var user _data = { "user" : user _name }
$ . ajax ( {
type : "POST" ,
url : "api/build_preauthkey_table" ,
data : JSON . stringify ( user _data ) ,
contentType : "application/json" ,
success : function ( table _data ) {
table = document . getElementById ( user _name + '-preauth-keys-collection' )
table . innerHTML = table _data
// The tooltips need to be re-initialized afterwards:
M . Tooltip . init ( document . querySelectorAll ( '.tooltipped' ) )
}
} )
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
2023-02-06 04:58:09 +00:00
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// The tooltips need to be re-initialized afterwards:
M . Tooltip . init ( document . querySelectorAll ( '.tooltipped' ) )
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error adding a pre-auth key" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
function expire _preauth _key ( user _name , key ) {
2023-04-21 01:28:56 +08:00
var data = { "user" : user _name , "key" : key }
2023-02-06 04:58:09 +00:00
$ . ajax ( {
2023-04-21 01:28:56 +08:00
type : "POST" ,
2023-02-06 04:58:09 +00:00
url : "api/expire_preauth_key" ,
data : JSON . stringify ( data ) ,
contentType : "application/json" ,
2023-04-21 01:28:56 +08:00
success : function ( response ) {
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// Send the completion toast
M . toast ( { html : 'PreAuth expired in ' + user _name } )
// If this is successful, we should reload the table and close the modal:
var user _data = { "user" : user _name }
$ . ajax ( {
type : "POST" ,
url : "api/build_preauthkey_table" ,
data : JSON . stringify ( user _data ) ,
contentType : "application/json" ,
success : function ( table _data ) {
table = document . getElementById ( user _name + '-preauth-keys-collection' )
table . innerHTML = table _data
// The tooltips need to be re-initialized afterwards:
M . Tooltip . init ( document . querySelectorAll ( '.tooltipped' ) )
}
} )
// Get the modal element and close it
modal _element = document . getElementById ( 'card_modal' )
M . Modal . getInstance ( modal _element ) . close ( )
2023-02-06 04:58:09 +00:00
Complete the major refactor
Major part of #73
Unfortunately, it wasn't possible to split it to multiple smaller
commits, since the changes touched the entire application substantially.
Here is a short list of major changes:
1. Create a separate library (headscale-api), which is used as a
convenient abstraction layer providing Pythonic interface with
Pydantic. Headscale API is fully asynchronous library, benefitting
from improved concurrency for backend requests thus increasing page
load speed, e.g., on "Machines" page.
2. Create a common common, validated with flask-pydantic API passthrough
layer from GUI to the backend.
3. Move authentication to a separate (auth.py), consolidating the
functionality in a single place (with better place for expansion in
the future).
4. Move configuration management to a separate module (config.py). Use
Pydantic's BaseSettings for reading values from environment, with
extensive validation and error reporting.
5. Reduce the number of health checks.
- Now, most are performed during server initialization. If any test
fails, the server is started in tainted mode, with only the error
page exposed (thus reducing the surface of attack in invalid
state).
- Key checks are implicit in the requests to the backend and
guarded by `@headscale.key_check_guard` decorator.
- Key renewal is moved to server-side scheduler.
6. Introduce type hints to the level satisfactory for mypy static
analysis. Also, enable some other linters in CI and add optional
pre-commit hooks.
7. Properly handle some error states. Instead of returning success and
handling different responses, if something fails, there is HTTP error
code and standard response for it.
8. General formatting, small rewrites for clarity and more idiomatic
Python constructs.
Signed-off-by: Marek Pikuła <marek.pikula@embevity.com>
2023-04-21 05:26:11 +00:00
// The tooltips need to be re-initialized afterwards:
M . Tooltip . init ( document . querySelectorAll ( '.tooltipped' ) )
} ,
error : function ( xhr , textStatus , errorThrown ) {
load _modal _generic ( "error" , "Error expiring a pre-auth key" , "Headscale response: " + JSON . parse ( xhr . responseText ) . message )
2023-02-06 04:58:09 +00:00
}
} )
}
//-----------------------------------------------------------
// User Page Helpers
//-----------------------------------------------------------
// Toggle expired items on the Users PreAuth section:
function toggle _expired ( ) {
var toggle _hide = document . getElementsByClassName ( 'expired-row' ) ;
2023-04-21 01:28:56 +08:00
var hidden = document . getElementsByClassName ( 'expired-row hide' ) ;
2023-02-06 04:58:09 +00:00
if ( hidden . length == 0 ) {
for ( var i = 0 ; i < toggle _hide . length ; i ++ ) {
toggle _hide [ i ] . className = "expired-row hide" ;
}
} else if ( hidden . length > 0 ) {
for ( var i = 0 ; i < toggle _hide . length ; i ++ ) {
toggle _hide [ i ] . className = "expired-row" ;
}
}
}
2023-02-10 14:01:31 +09:00
// Copy a PreAuth Key to the clipboard. Show only the Prefix by default
function copy _preauth _key ( key ) {
navigator . clipboard . writeText ( key ) ;
2023-04-21 01:28:56 +08:00
M . toast ( { html : 'PreAuth key copied to clipboard.' } )
2023-02-10 14:01:31 +09:00
}