Skip to content

Commit 256039a

Browse files
feat: add config, certs, database, users, and jwt
1 parent 5cdbc61 commit 256039a

File tree

24 files changed

+716
-59
lines changed

24 files changed

+716
-59
lines changed

.cargo/config.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ linker = "arm-linux-gnueabihf-gcc"
2727

2828
[target.arm-unknown-linux-musleabihf]
2929
linker = "arm-linux-gnueabihf-gcc"
30+
31+
[target.x86_64-pc-windows-gnu]
32+
linker = "C:\\msys2\\ucrt64\\bin\\gcc.exe"
33+
ar = "C:\\msys2\\ucrt64\\bin\\ar.exe"

Cargo.toml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,29 @@ path = "src/main.rs"
4141

4242
[dependencies]
4343
# ensure deps are compatible: https://www.gnu.org/licenses/license-list.en.html#GPLCompatibleLicenses
44+
base64 = "0.22.1"
45+
bcrypt = "0.17.0"
4446
cargo_metadata = "0.19.1"
4547
chrono = "0.4.39"
48+
config = "0.15.7"
49+
diesel = { version = "2.2.7", features = ["sqlite"] }
50+
diesel_migrations = "2.2.0"
51+
dirs = "6.0.0"
4652
fern = { version = "0.7.1", features = ["colored"] }
4753
image = "0.25.5"
54+
jsonwebtoken = "9.3.1"
55+
libsqlite3-sys = { version = "0.31", features = ["bundled"] } # this is needed for proper linking
4856
log = "0.4.25"
57+
once_cell = "1.20.3"
58+
rand = "0.9.0"
59+
rcgen = "0.13.2"
4960
regex = "1.11.1"
50-
rocket = "0.5.1"
61+
rocket = { version = "0.5.1", features = ["tls"] }
5162
rocket_okapi = { version = "0.9.0", features = ["swagger", "rapidoc"] }
63+
rocket_sync_db_pools = { version = "0.1.0", features = ["diesel_sqlite_pool"] }
5264
schemars = "0.8.1"
5365
serde = "1.0.217"
66+
serde_json = "1.0.138"
5467
tao = "0.31.1"
5568
tray-icon = "0.19.2"
5669
webbrowser = "1.0.3"

assets/Koko.png

35.4 KB
Loading

assets/Koko.svg

Lines changed: 69 additions & 0 deletions
Loading

assets/icon.ico

-548 Bytes
Binary file not shown.

assets/icon.png

3.66 KB
Loading

docs/README.md

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,22 @@
55
</div>
66

77
<div align="center">
8-
<a href="https://github.com/LizardByte/Koko">
9-
<img src="https://img.shields.io/github/stars/lizardbyte/koko.svg?logo=github&style=for-the-badge" alt="GitHub stars">
10-
</a>
8+
<a href="https://github.com/LizardByte/Koko"><img src="https://img.shields.io/github/stars/lizardbyte/koko.svg?logo=github&style=for-the-badge" alt="GitHub stars"></a>
119
<!-- disabled for now
12-
<a href="https://github.com/LizardByte/Koko/releases/latest">
13-
<img src="https://img.shields.io/github/downloads/lizardbyte/koko/total.svg?style=for-the-badge&logo=github" alt="GitHub Releases">
14-
</a>
15-
<a href="https://hub.docker.com/r/lizardbyte/koko">
16-
<img src="https://img.shields.io/docker/pulls/lizardbyte/koko.svg?style=for-the-badge&logo=docker" alt="Docker">
17-
</a>
18-
<a href="https://github.com/LizardByte/Koko/pkgs/container/koko">
19-
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fipitio.github.io%2Fbackage%2FLizardByte%Koko%2Fkoko.json&query=%24.downloads&label=ghcr%20pulls&style=for-the-badge&logo=github" alt="GHCR">
20-
</a>
21-
<a href="https://flathub.org/apps/dev.lizardbyte.app.Koko">
22-
<img src="https://img.shields.io/flathub/downloads/dev.lizardbyte.app.Koko?style=for-the-badge&logo=flathub" alt="Flathub installs">
23-
</a>
24-
<a href="https://flathub.org/apps/dev.lizardbyte.app.Koko">
25-
<img src="https://img.shields.io/flathub/v/dev.lizardbyte.app.Koko?style=for-the-badge&logo=flathub" alt="Flathub Version">
26-
</a>
27-
<a href="https://github.com/microsoft/winget-pkgs/tree/master/manifests/l/LizardByte/Koko">
28-
<img src="https://img.shields.io/winget/v/LizardByte.Koko?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHuSURBVFhH7ZfNTtRQGIYZiMDwN/IrCAqIhMSNKxcmymVwG+5dcDVsWHgDrtxwCYQVl+BChzDEwSnPY+eQ0sxoOz1mQuBNnpyvTdvz9jun5/SrjfxnJUkyQbMEz2ELduF1l0YUA3QyTrMAa2AnPtyOXsELeAYNyKtV2EC3k3lYgTOwg09ghy/BTp7CKBRV844BOpmmMV2+ySb4BmInG7AKY7AHH+EYqqhZo9PPBG/BVDlOizAD/XQFmnoPXzxRQX8M/CCYS48L6RIc4ygGHK9WGg9HZSZMUNRPVwNJGg5Hg2Qgqh4N3FsDsb6EmgYm07iwwvUxstdxJTwgmILf4CfZ6bb5OHANX8GN5x20IVxnG8ge94pt2xpwU3GnCwayF4Q2G2vgFLzHndFzQdk4q77nNfCdwL28qNyMtmEf3A1/QV5FjDiPWo5jrwf8TWZChTlgJvL4F9QL50/A43qVidTvLcuoM2wDQ1+IkgefgUpLcYwMVBqCKNJA2b0gKNocOIITOIef8C/F/CdMbh/GklynsSawKLHS8d9/B1x2LUqsfFyy3TMsWj5A1cLkotDbYO4JjWWZlZEGv8EbOIR1CAVN2eG8W5oNKgxaeC6DmTJjZs7ixUxpznLPLT+v4sXpoMLcLI3mzFSonDXIEI/M3QCIO4YuimBJ/gAAAABJRU5ErkJggg==" alt="Winget Version">
29-
</a>
30-
<a href="https://gurubase.io/g/koko">
31-
<img src="https://img.shields.io/badge/Gurubase-Ask%20Guru-ef1a1b?style=for-the-badge&logo=data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDIBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIABgAGAMBIgACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOLqSO3mlilljido4QGkYDIQEgAn05IH41seFo7aS+uRKlrJci2Y2cd2QImlyOGyQPu7sA8ZxXapAlvpThbPRkv7nTQWhDoIZZRc/XaSAOmcZGOnFfP06XMr3P17F5iqE+Tl1uuvf9Lde55dRW74pit4r61EcdtFdG2U3kVqQY0lyeBgkD5duQOASawqykuV2O6jV9rTU0rXLNjf3Om3QubSXy5QCudoYEEYIIOQR7GnahqV3qk6zXk3mOqhFAUKqqOyqAAByeAKqUUXdrFezhz89lfv1+8KKKKRZ//Z" alt="Gurubase">
32-
</a>
10+
<a href="https://github.com/LizardByte/Koko/releases/latest"><img src="https://img.shields.io/github/downloads/lizardbyte/koko/total.svg?style=for-the-badge&logo=github" alt="GitHub Releases"></a>
11+
<a href="https://hub.docker.com/r/lizardbyte/koko"><img src="https://img.shields.io/docker/pulls/lizardbyte/koko.svg?style=for-the-badge&logo=docker" alt="Docker"></a>
12+
<a href="https://github.com/LizardByte/Koko/pkgs/container/koko"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fipitio.github.io%2Fbackage%2FLizardByte%Koko%2Fkoko.json&query=%24.downloads&label=ghcr%20pulls&style=for-the-badge&logo=github" alt="GHCR"></a>
13+
<a href="https://flathub.org/apps/dev.lizardbyte.app.Koko"><img src="https://img.shields.io/flathub/downloads/dev.lizardbyte.app.Koko?style=for-the-badge&logo=flathub" alt="Flathub installs"></a>
14+
<a href="https://flathub.org/apps/dev.lizardbyte.app.Koko"><img src="https://img.shields.io/flathub/v/dev.lizardbyte.app.Koko?style=for-the-badge&logo=flathub" alt="Flathub Version"></a>
15+
<a href="https://github.com/microsoft/winget-pkgs/tree/master/manifests/l/LizardByte/Koko"><img src="https://img.shields.io/winget/v/LizardByte.Koko?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHuSURBVFhH7ZfNTtRQGIYZiMDwN/IrCAqIhMSNKxcmymVwG+5dcDVsWHgDrtxwCYQVl+BChzDEwSnPY+eQ0sxoOz1mQuBNnpyvTdvz9jun5/SrjfxnJUkyQbMEz2ELduF1l0YUA3QyTrMAa2AnPtyOXsELeAYNyKtV2EC3k3lYgTOwg09ghy/BTp7CKBRV844BOpmmMV2+ySb4BmInG7AKY7AHH+EYqqhZo9PPBG/BVDlOizAD/XQFmnoPXzxRQX8M/CCYS48L6RIc4ygGHK9WGg9HZSZMUNRPVwNJGg5Hg2Qgqh4N3FsDsb6EmgYm07iwwvUxstdxJTwgmILf4CfZ6bb5OHANX8GN5x20IVxnG8ge94pt2xpwU3GnCwayF4Q2G2vgFLzHndFzQdk4q77nNfCdwL28qNyMtmEf3A1/QV5FjDiPWo5jrwf8TWZChTlgJvL4F9QL50/A43qVidTvLcuoM2wDQ1+IkgefgUpLcYwMVBqCKNJA2b0gKNocOIITOIef8C/F/CdMbh/GklynsSawKLHS8d9/B1x2LUqsfFyy3TMsWj5A1cLkotDbYO4JjWWZlZEGv8EbOIR1CAVN2eG8W5oNKgxaeC6DmTJjZs7ixUxpznLPLT+v4sXpoMLcLI3mzFSonDXIEI/M3QCIO4YuimBJ/gAAAABJRU5ErkJggg==" alt="Winget Version"></a>
16+
<a href="https://gurubase.io/g/koko"><img src="https://img.shields.io/badge/Gurubase-Ask%20Guru-ef1a1b?style=for-the-badge&logo=data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDIBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIABgAGAMBIgACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOLqSO3mlilljido4QGkYDIQEgAn05IH41seFo7aS+uRKlrJci2Y2cd2QImlyOGyQPu7sA8ZxXapAlvpThbPRkv7nTQWhDoIZZRc/XaSAOmcZGOnFfP06XMr3P17F5iqE+Tl1uuvf9Lde55dRW74pit4r61EcdtFdG2U3kVqQY0lyeBgkD5duQOASawqykuV2O6jV9rTU0rXLNjf3Om3QubSXy5QCudoYEEYIIOQR7GnahqV3qk6zXk3mOqhFAUKqqOyqAAByeAKqUUXdrFezhz89lfv1+8KKKKRZ//Z" alt="Gurubase"></a>
3317
-->
34-
<a href="https://github.com/LizardByte/Koko/actions/workflows/ci.yml?query=branch%3Amaster">
35-
<img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/koko/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (CI)">
36-
</a>
18+
<a href="https://github.com/LizardByte/Koko/actions/workflows/ci.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/koko/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (CI)"></a>
3719
<!-- disabled for now
38-
<a href="https://github.com/LizardByte/Koko/actions/workflows/localize.yml?query=branch%3Amaster">
39-
<img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/koko/localize.yml.svg?branch=master&label=localize%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (localize)">
40-
</a>
20+
<a href="https://github.com/LizardByte/Koko/actions/workflows/localize.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/koko/localize.yml.svg?branch=master&label=localize%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (localize)"></a>
4121
-->
42-
<a href="https://docs.lizardbyte.dev/projects/koko">
43-
<img src="https://img.shields.io/readthedocs/koko.svg?label=Docs&style=for-the-badge&logo=readthedocs" alt="Read the Docs">
44-
</a>
45-
<a href="https://codecov.io/gh/LizardByte/Koko">
46-
<img src="https://img.shields.io/codecov/c/gh/LizardByte/Koko?token=wkbk5nOLAr&style=for-the-badge&logo=codecov&label=codecov" alt="Codecov">
47-
</a>
22+
<a href="https://docs.lizardbyte.dev/projects/koko"><img src="https://img.shields.io/readthedocs/koko.svg?label=Docs&style=for-the-badge&logo=readthedocs" alt="Read the Docs"></a>
23+
<a href="https://codecov.io/gh/LizardByte/Koko"><img src="https://img.shields.io/codecov/c/gh/LizardByte/Koko?token=wkbk5nOLAr&style=for-the-badge&logo=codecov&label=codecov" alt="Codecov"></a>
4824
</div>
4925

5026
## ℹ️ About
@@ -56,11 +32,40 @@ If you are interested in this project, please leave a star and watch the reposit
5632

5733
If you would like to contribute, please reach out on our [discord](https://app.lizardbyte.dev/discord) server.
5834

35+
## Configuration
36+
37+
Koko uses a YAML configuration file to set up the server.
38+
39+
The file must be named `settings.yml` and be placed in the following location, depending on your OS.
40+
41+
| OS | Location |
42+
|---------|------------------------------------------|
43+
| Linux | `$XDG_CONFIG_HOME/Koko` |
44+
| macOS | `$HOME/Library/Application Support/Koko` |
45+
| Windows | `%LOCALAPPDATA%\Koko` |
46+
47+
Only the non default values need to be set in the configuration file.
48+
An example with all the default values is shown below.
49+
50+
```yml
51+
---
52+
general:
53+
data_dir: 'data'
54+
55+
server:
56+
use_https: true
57+
address: '127.0.0.1'
58+
port: 9191
59+
cert_path: 'cert.pem'
60+
key_path: 'key.pem'
61+
use_custom_certs: false
62+
```
63+
5964
## 📝 TODO
6065
This list is not all-inclusive, and just meant to be a very high level for the initial design.
6166
6267
- [ ] Branding
63-
- [ ] Koko logo
68+
- [x] Koko logo
6469
- [ ] Koko banner
6570
- [ ] Tray icons for different states/activity
6671
- [ ] Publishing (enabling readme badges as required)
@@ -74,15 +79,16 @@ This list is not all-inclusive, and just meant to be a very high level for the i
7479
- [x] Unit Testing
7580
- [ ] doc tests
7681
- [x] Coverage
77-
- [ ] Settings/Config
82+
- [x] Settings/Config
7883
- [ ] Notification System
7984
- [ ] System Notifications
8085
- [ ] Discord
8186
- [ ] Webhooks
82-
- [ ] Database
87+
- [x] Database
8388
- [ ] Backend
84-
- [ ] Authentication
89+
- [x] Authentication
8590
- [ ] API
91+
- [x] Certs/SSL
8692
- [ ] Media Scanner
8793
- [ ] Media Player
8894
- [x] Legal/Licensing info on dependencies
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE IF EXISTS users;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CREATE TABLE IF NOT EXISTS users (
2+
id INTEGER PRIMARY KEY AUTOINCREMENT,
3+
username TEXT NOT NULL UNIQUE,
4+
password TEXT NOT NULL,
5+
password_salt TEXT NOT NULL,
6+
pin TEXT DEFAULT NULL,
7+
pin_salt TEXT DEFAULT NULL,
8+
admin BOOLEAN NOT NULL DEFAULT FALSE
9+
);

src/auth.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#![doc = "Authentication utilities for the application."]
2+
3+
// lib imports
4+
use base64::{engine::general_purpose, Engine as _};
5+
use bcrypt::{hash, DEFAULT_COST};
6+
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
7+
use once_cell::sync::Lazy;
8+
use rand::distr::Alphanumeric;
9+
use rand::{rng, Rng};
10+
use rocket::outcome::Outcome;
11+
use rocket::request::{self, FromRequest, Request};
12+
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
13+
use serde::{Deserialize, Serialize};
14+
15+
/// Claims for the JWT.
16+
#[derive(Debug, Serialize, Deserialize)]
17+
pub struct Claims {
18+
sub: String,
19+
exp: usize,
20+
}
21+
22+
const BEARER: &str = "Bearer ";
23+
24+
/// Create a JWT token.
25+
pub fn create_token(
26+
user_id: &str,
27+
secret: &str,
28+
) -> String {
29+
let expiration = chrono::Utc::now()
30+
.checked_add_signed(chrono::Duration::seconds(60))
31+
.expect("valid timestamp")
32+
.timestamp();
33+
34+
let claims = Claims {
35+
sub: user_id.to_owned(),
36+
exp: expiration as usize,
37+
};
38+
39+
encode(
40+
&Header::default(),
41+
&claims,
42+
&EncodingKey::from_secret(secret.as_ref()),
43+
)
44+
.unwrap()
45+
}
46+
47+
/// Decode a JWT token.
48+
pub fn decode_token(
49+
token: &str,
50+
secret: &str,
51+
) -> Result<Claims, jsonwebtoken::errors::Error> {
52+
decode::<Claims>(
53+
token,
54+
&DecodingKey::from_secret(secret.as_ref()),
55+
&Validation::default(),
56+
)
57+
.map(|data| data.claims)
58+
}
59+
60+
#[rocket::async_trait]
61+
impl<'r> FromRequest<'r> for Claims {
62+
type Error = ();
63+
64+
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
65+
let keys: Vec<_> = request.headers().get("Authorization").collect();
66+
if keys.len() != 1 {
67+
return Outcome::Error((rocket::http::Status::Unauthorized, ()));
68+
}
69+
70+
if !keys[0].starts_with(BEARER) {
71+
return Outcome::Error((rocket::http::Status::Unauthorized, ()));
72+
}
73+
74+
let token = &keys[0][BEARER.len()..];
75+
let secret = get_jwt_secret();
76+
77+
match decode_token(token, secret) {
78+
Ok(claims) => Outcome::Success(claims),
79+
Err(_) => Outcome::Error((rocket::http::Status::Unauthorized, ())),
80+
}
81+
}
82+
}
83+
84+
impl OpenApiFromRequest<'_> for Claims {
85+
fn from_request_input(
86+
_gen: &mut rocket_okapi::gen::OpenApiGenerator,
87+
_name: String,
88+
_required: bool,
89+
) -> rocket_okapi::Result<RequestHeaderInput> {
90+
Ok(RequestHeaderInput::None)
91+
}
92+
}
93+
94+
static JWT_SECRET: Lazy<String> = Lazy::new(|| {
95+
let random_bytes: [u8; 32] = rand::rng().random();
96+
general_purpose::STANDARD.encode(random_bytes)
97+
});
98+
99+
fn get_jwt_secret() -> &'static str {
100+
&JWT_SECRET
101+
}
102+
103+
pub(crate) fn generate_salt() -> String {
104+
rng()
105+
.sample_iter(&Alphanumeric)
106+
.take(16)
107+
.map(char::from)
108+
.collect()
109+
}
110+
111+
pub(crate) fn hash_with_salt(
112+
salt: String,
113+
string: &str,
114+
) -> String {
115+
let salted_input = format!("{}{}", salt, string);
116+
hash(salted_input, DEFAULT_COST).unwrap()
117+
}

0 commit comments

Comments
 (0)