Compare commits

..

No commits in common. "master" and "4ca873e794aeea052dd42ceaecfc12041d5db3c2" have entirely different histories.

20 changed files with 63 additions and 196 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -1,8 +0,0 @@
### How to get Backblaze API Token
1. Visit the following link and authorize: https://secure.backblaze.com/user_signin.htm
2. On the left side of the interface, select **App Keys** in the **B2 Cloud Storage** subcategory.
3. Click on the blue **Generate New Master Application Key** button.
4. In the appeared pop-up window confirm the generation.
5. Save _keyID_ and _applicationKey_ in the safe place. For example, in the password manager.
![Backblaze token setup](resource:assets/images/gifs/Backblaze.gif)

View File

@ -1,8 +0,0 @@
### Как получить Backblaze API Token
1. Переходим по ссылке https://secure.backblaze.com/user_signin.htm и авторизуемся.
2. В левой части интерфейса выбираем **App Keys** в подкатегории **"Account"**.
3. Нажимаем на синюю кнопку **Generate New Master Application Key**.
4. Во всплывающем окне подтверждаем генерацию.
5. Сохраняем _keyID_ и _applicationKey_ в надёжном месте. Например в менеджере паролей.
![Backblaze token setup](resource:assets/images/gifs/Backblaze.gif)

View File

@ -1,17 +0,0 @@
### How to get Cloudflare API Token
1. Visit the following link: https://dash.cloudflare.com/
2. the right corner, click on the profile icon (a man in a circle). For the mobile version of the site, in the upper left corner, click the **Menu** button (three horizontal bars), in the dropdown menu, click on **My Profile**
3. There are four configuration categories to choose from: *Communication*, *Authentication*, **API Tokens**, *Session*. Choose **API Tokens**.
4. Click on **Create Token** button.
5. Go down to the bottom and see the **Create Custom Token** field and press **Get Started** button on the right side.
6. In the **Token Name** field, give your token a name.
7. Next we have Permissions. In the leftmost field, select **Zone**. In the longest field, center, select **DNS**. In the rightmost field, select **Edit**.
8. Next, right under this line, click Add More. Similar field will appear.
9. In the leftmost field of the new line, select, similar to the last line — **Zone**. In the center — a little different. Here choose the same as in the left — **Zone**. In the rightmost field, select **Read**.
10. Next look at **Zone Resources**. Under this inscription there is a line with two fields. The left must have **Include** and the right must have **Specific Zone**. Once you select Specific Zone, another field appears on the right. Choose your domain in it.
11. Flick to the bottom and press the blue **Continue to Summary** button.
12. Check if you got everything right. A similar string must be present: *Domain — DNS:Edit, Zone:Read*.
13. Click on **Create Token**.
14. We copy the created token, and save it in a reliable place (preferably in the password manager).
![Cloudflare token setup](resource:assets/images/gifs/CloudFlare.gif)

View File

@ -1,15 +0,0 @@
### Как получить Cloudflare API Token
1. Переходим по [ссылке](https://dash.cloudflare.com/) и авторизуемся в ранее созданном аккаунте. https://dash.cloudflare.com/
В правом углу кликаем на иконку профиля (человечек в кружочке). Для мобильной версии сайта, в верхнем левом углу, нажимаем кнопку **Меню** (три горизонтальных полоски), в выпавшем меню, ищем пункт **My Profile**.
3. Нам предлагается на выбор, четыре категории настройки: **Preferences**, **Authentication**, **API Tokens**, **Sessions**. Выбираем **API Tokens**.
4. Самым первым пунктом видим кнопку **Create Token**. С полной уверенностью в себе и желанием обрести приватность, нажимаем на неё.
5. Спускаемся в самый низ и видим поле **Create Custom Token** и кнопку **Get Started** с правой стороны. Нажимаем.
6. В поле **Token Name** даём своему токену имя. Можете покреативить и отнестись к этому как к наименованию домашнего зверька :)
7. Далее, у нас **Permissions**. В первом поле выбираем Zone. Во втором поле, по центру, выбираем **DNS**. В последнем поле выбираем **Edit**.
8. Далее смотрим на **Zone Resources**. Под этой надписью есть строка с двумя полями. В первом должно быть **Include**, а во втором — **Specific Zone**. Как только Вы выберите **Specific Zone**, справа появится ещё одно поле. В нём выбираем наш домен.
9. Листаем в самый низ и нажимаем на синюю кнопку **Continue to Summary**.
10. Проверяем, всё ли мы правильно выбрали. Должна присутствовать подобная строка: ваш.домен — **DNS:Edit, Zone:Read**.
11. Нажимаем **Create Token**.
12. Копируем созданный токен, и сохраняем его в надёжном месте (желательно — в менеджере паролей).
![Cloudflare token setup](resource:assets/images/gifs/CloudFlare.gif)

View File

@ -1,4 +1,3 @@
### How to get Hetzner API Token
1. Visit the following [link](https://console.hetzner.cloud/) and sign
into newly created account.
2. Enter into previously created project. If you haven't created one,
@ -18,6 +17,4 @@
**permissions**. Pick **Read & Write**.
8. Click **Generate API Token.**
9. After that, our key will be shown. Store it in the reliable place,
or in the password manager, which is better.
![Hetzner token setup](resource:assets/images/gifs/Hetzner.gif)
or in the password manager, which is better.

View File

@ -4,6 +4,4 @@
3. Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика).
4. Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему.
5. В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же Вы используете мобильную версию сайта, в нижнем правом углу Вы увидите красный плюсик. Нажимаем на эту кнопку.
6. В поле Description, даём нашему токену название (это может быть любое название, которые Вам нравиться. Сути оно не меняет.
![Hetzner token setup](resource:assets/images/gifs/Hetzner.gif)
6. В поле Description, даём нашему токену название (это может быть любое название, которые Вам нравиться. Сути оно не меняет.

View File

@ -127,7 +127,6 @@
"mail": {
"title": "E-Mail",
"subtitle": "E-Mail for company and family.",
"login_info": "Use username and password from users tab. IMAP port is 143 with STARTTLS, SMTP port is 587 with STARTTLS.",
"bottom_sheet": {
"1": "To connect to the mailserver, please use {} domain alongside with username and password, that you created. Also feel free to invite",
"2": "new users"
@ -136,7 +135,6 @@
"messenger": {
"title": "Messenger",
"subtitle": "Telegram or Signal not so private as Delta.Chat that uses your private server.",
"login_info": "Use the same username and password as for e-mail.",
"bottom_sheet": {
"1": "For connection, please use {} domain and credentials that you created."
}
@ -144,7 +142,6 @@
"password_manager": {
"title": "Password Manager",
"subtitle": "Base of your security. Bitwarden will help you to create, store and move passwords between devices, as well as input them, when requested using autocompletion.",
"login_info": "You will have to create an account on the website.",
"bottom_sheet": {
"1": "You can connect to the service and create a user via this link:"
}
@ -152,7 +149,6 @@
"video": {
"title": "Videomeet",
"subtitle": "Zoom and Google Meet are good, but Jitsi Meet is a worth alternative that also gives you confidence that you're not being listened.",
"login_info": "No account needed.",
"bottom_sheet": {
"1": "Using Jitsi as simple as just visiting this link:"
}
@ -160,7 +156,6 @@
"cloud": {
"title": "Cloud Storage",
"subtitle": "Do not allow cloud services to read your data by using NextCloud.",
"login_info": "Login is admin, password is the same as with your main user. Create new accounts in Nextcloud interface.",
"bottom_sheet": {
"1": "You can connect and create a new user here:"
}
@ -168,7 +163,6 @@
"social_network": {
"title": "Social Network",
"subtitle": "It's hard to believe, but it became possible to create your own social network, with your own rules and target audience.",
"login_info": "You will have to create an account on the website.",
"bottom_sheet": {
"1": "You can connect and create new social user here:"
}
@ -176,7 +170,6 @@
"git": {
"title": "Git Server",
"subtitle": "Private alternative to the Github, that belongs to you, but not a Microsoft.",
"login_info": "You will have to create an account on the website. First user will become an admin.",
"bottom_sheet": {
"1": "You can connect and create a new user here:"
}

View File

@ -128,7 +128,6 @@
"mail": {
"title": "Почта",
"subtitle": "Электронная почта для семьи или компании.",
"login_info": "Используйте логин и пароль из вкладки пользователей. IMAP порт: 143, STARTTLS. SMTP порт: 587, STARTTLS.",
"bottom_sheet": {
"1": "Для подключения почтового ящика используйте {} и профиль, который Вы создали. Так же приглашайте",
"2": "новых пользователей."
@ -137,7 +136,6 @@
"messenger": {
"title": "Мессенджер",
"subtitle": "Telegram и Signal не так приватны, как Delta.Chat — он использует Ваш личный сервер.",
"login_info": "Используйте те же логин и пароль, что и для почты.",
"bottom_sheet": {
"1": "Для подключения используйте {} и логин пароль, который Вы создали."
}
@ -145,7 +143,6 @@
"password_manager": {
"title": "Менеджер паролей",
"subtitle": "Это фундамент Вашей безопасности. Создавать, хранить, копировать пароли между устройствами и вбивать их в формы поможет Bitwarden.",
"login_info": "Аккаунт нужно создать на сайте.",
"bottom_sheet": {
"1": "Подключиться к серверу и создать пользователя можно по адресу:."
}
@ -153,7 +150,6 @@
"video": {
"title": "Видеоконференция",
"subtitle": "Jitsi meet — отличный аналог Zoom и Google meet который помимо удобства ещё и гарантирует Вам защищённые высококачественные видеоконференции.",
"login_info": "Аккаунт не требуется.",
"bottom_sheet": {
"1": "Для использования просто перейдите по ссылке:."
}
@ -161,7 +157,6 @@
"cloud": {
"title": "Файловое облако",
"subtitle": "Не позволяйте облачным сервисам просматривать ваши данные. Используйте NextCloud — надёжный дом для всех Ваших данных.",
"login_info": "Логин администратора: admin, пароль такой же как у основного пользователя. Создавайте новых пользователей в интерфейсе администратора NextCloud.",
"bottom_sheet": {
"1": "Подключиться к серверу и создать пользователя можно по адресу:."
}
@ -169,7 +164,6 @@
"social_network": {
"title": "Социальная сеть",
"subtitle": "Сложно поверить, но стало возможным создать свою собственную социальную сеть, со своими правилами и аудиторией.",
"login_info": "Аккаунт нужно создать на сайте.",
"bottom_sheet": {
"1": "Подключиться к серверу и создать пользователя можно по адресу:."
}
@ -177,7 +171,6 @@
"git": {
"title": "Git-сервер",
"subtitle": "Приватная альтернатива Github, которая принадлежит вам, а не Microsoft.",
"login_info": "Аккаунт нужно создать на сайте. Первый зарегистрированный пользователь становится администратором.",
"bottom_sheet": {
"1": "Подключиться к серверу и создать пользователя можно по адресу:."
}

View File

@ -1,4 +0,0 @@
- Show progress bar on upgrading/restarting server
- Implemented user deletion
- Built-in documentation improvement
- Minor bug fixes

View File

@ -114,8 +114,7 @@ class HetznerApi extends ApiMap {
final apiToken = StringGenerators.apiToken();
// Replace all non-alphanumeric characters with an underscore
final hostname = domainName.split('.')[0].replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
final hostname = domainName.split('.')[0];
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
/// check the branch name, it could be "development" or "master".

View File

@ -69,46 +69,6 @@ extension ServiceTypesExt on ServiceTypes {
}
}
String get loginInfo {
switch (this) {
case ServiceTypes.mail:
return 'services.mail.login_info'.tr();
case ServiceTypes.messenger:
return 'services.messenger.login_info'.tr();
case ServiceTypes.passwordManager:
return 'services.password_manager.login_info'.tr();
case ServiceTypes.video:
return 'services.video.login_info'.tr();
case ServiceTypes.cloud:
return 'services.cloud.login_info'.tr();
case ServiceTypes.socialNetwork:
return 'services.social_network.login_info'.tr();
case ServiceTypes.git:
return 'services.git.login_info'.tr();
case ServiceTypes.vpn:
return '';
}
}
String get subdomain {
switch (this) {
case ServiceTypes.passwordManager:
return 'password';
case ServiceTypes.video:
return 'meet';
case ServiceTypes.cloud:
return 'cloud';
case ServiceTypes.socialNetwork:
return 'social';
case ServiceTypes.git:
return 'git';
case ServiceTypes.vpn:
case ServiceTypes.messenger:
default:
return '';
}
}
IconData get icon {
switch (this) {
case ServiceTypes.mail:

View File

@ -6,7 +6,6 @@ import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
import 'package:selfprivacy/logic/models/backup.dart';
import 'package:selfprivacy/logic/api_maps/server.dart';
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
import 'package:easy_localization/easy_localization.dart';
part 'backups_state.dart';
@ -86,7 +85,7 @@ class BackupsCubit extends AppConfigDependendCubit<BackupsState> {
Future<void> createBucket() async {
emit(state.copyWith(preventActions: true));
final domain =
appConfigCubit.state.cloudFlareDomain!.domainName.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
appConfigCubit.state.cloudFlareDomain!.domainName.replaceAll('.', '-');
final serverId = appConfigCubit.state.hetznerServer!.id;
var bucketName = 'selfprivacy-$domain-$serverId';
// If bucket name is too long, shorten it
@ -152,8 +151,7 @@ class BackupsCubit extends AppConfigDependendCubit<BackupsState> {
Future<void> forceUpdateBackups() async {
emit(state.copyWith(preventActions: true));
await api.forceBackupListReload();
getIt<NavigationService>()
.showSnackBar('providers.backup.refetchingList'.tr());
getIt<NavigationService>().showSnackBar('providers.backup.refetchingList');
emit(state.copyWith(preventActions: false));
}

View File

@ -137,8 +137,7 @@ class InitializingPage extends StatelessWidget {
),
SizedBox(height: 10),
BrandButton.text(
onPressed: () =>
_showModal(context, _HowTo(fileName: 'how_hetzner')),
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.how'.tr(),
),
],
@ -193,11 +192,7 @@ class InitializingPage extends StatelessWidget {
),
SizedBox(height: 10),
BrandButton.text(
onPressed: () => _showModal(
context,
_HowTo(
fileName: 'how_cloudflare',
)),
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.how'.tr(),
),
],
@ -248,11 +243,7 @@ class InitializingPage extends StatelessWidget {
),
SizedBox(height: 10),
BrandButton.text(
onPressed: () => _showModal(
context,
_HowTo(
fileName: 'how_backblaze',
)),
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.how'.tr(),
),
],
@ -343,9 +334,12 @@ class InitializingPage extends StatelessWidget {
text: 'initializing.10'.tr(),
),
],
SizedBox(
height: 10,
width: double.infinity,
SizedBox(height: 10),
Spacer(),
SizedBox(height: 10),
BrandButton.text(
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.how'.tr(),
),
],
);
@ -409,6 +403,11 @@ class InitializingPage extends StatelessWidget {
: () => context.read<RootUserFormCubit>().trySubmit(),
text: 'basis.connect'.tr(),
),
SizedBox(height: 10),
BrandButton.text(
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.how'.tr(),
),
],
);
}),
@ -432,6 +431,11 @@ class InitializingPage extends StatelessWidget {
: () => appConfigCubit.createServerAndSetDnsRecords(),
text: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(),
),
Spacer(flex: 2),
BrandButton.text(
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.what'.tr(),
),
],
);
});
@ -478,6 +482,13 @@ class InitializingPage extends StatelessWidget {
],
),
if (state.isLoading) BrandText.body2('initializing.17'.tr()),
Spacer(
flex: 2,
),
BrandButton.text(
onPressed: () => _showModal(context, _HowHetzner()),
title: 'initializing.what'.tr(),
),
],
);
});
@ -492,14 +503,11 @@ class InitializingPage extends StatelessWidget {
}
}
class _HowTo extends StatelessWidget {
const _HowTo({
class _HowHetzner extends StatelessWidget {
const _HowHetzner({
Key? key,
required this.fileName,
}) : super(key: key);
final String fileName;
@override
Widget build(BuildContext context) {
return BrandBottomSheet(
@ -507,7 +515,7 @@ class _HowTo extends StatelessWidget {
child: Padding(
padding: paddingH15V0,
child: BrandMarkdown(
fileName: fileName,
fileName: 'how_hetzner',
),
),
);

View File

@ -38,23 +38,6 @@ class ServicesPage extends StatefulWidget {
_ServicesPageState createState() => _ServicesPageState();
}
void _launchURL(url) async {
var _possible = await canLaunch(url);
if (_possible) {
try {
await launch(
url,
enableJavaScript: true,
);
} catch (e) {
print(e);
}
} else {
throw 'Could not launch $url';
}
}
class _ServicesPageState extends State<ServicesPage> {
@override
Widget build(BuildContext context) {
@ -111,9 +94,6 @@ class _Card extends StatelessWidget {
(!switchableServices.contains(serviceType) ||
serviceState.isEnableByType(serviceType));
var config = context.watch<AppConfigCubit>().state;
var domainName = UiHelpers.getDomainName(config);
return GestureDetector(
onTap: isSwithOn
? () => showDialog<void>(
@ -183,30 +163,6 @@ class _Card extends StatelessWidget {
SizedBox(height: 10),
BrandText.h2(serviceType.title),
SizedBox(height: 10),
if (serviceType.subdomain != '')
Column(
children: [
GestureDetector(
onTap: () => _launchURL(
'https://${serviceType.subdomain}.$domainName'),
child: Text(
'${serviceType.subdomain}.$domainName',
style: linkStyle,
),
),
SizedBox(height: 10),
],
),
if (serviceType == ServiceTypes.mail)
Column(children: [
Text(
domainName,
style: linkStyle,
),
SizedBox(height: 10),
]),
BrandText.body2(serviceType.loginInfo),
SizedBox(height: 10),
BrandText.body2(serviceType.subtitle),
SizedBox(height: 10),
],
@ -482,4 +438,21 @@ class _ServiceDetails extends StatelessWidget {
),
);
}
void _launchURL(url) async {
var _possible = await canLaunch(url);
if (_possible) {
try {
await launch(
url,
enableJavaScript: true,
);
} catch (e) {
print(e);
}
} else {
throw 'Could not launch $url';
}
}
}

View File

@ -75,8 +75,9 @@ class _UserDetails extends StatelessWidget {
),
),
onPressed: () {
context.read<JobsCubit>().addJob(
DeleteUserJob(user: user));
context
.read<JobsCubit>()
.addJob(DeleteUserJob(user: user));
Navigator.of(context)
..pop()
..pop();

View File

@ -42,7 +42,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.1"
version: "2.8.2"
auto_size_text:
dependency: "direct main"
description:
@ -133,7 +133,7 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0"
charcode:
dependency: transitive
description:
@ -510,7 +510,7 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.10"
version: "0.12.11"
meta:
dependency: transitive
description:
@ -900,21 +900,21 @@ packages:
name: test
url: "https://pub.dartlang.org"
source: hosted
version: "1.17.10"
version: "1.17.12"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
version: "0.4.3"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
version: "0.4.2"
timing:
dependency: transitive
description:
@ -984,7 +984,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
vm_service:
dependency: transitive
description:
@ -1077,5 +1077,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.13.4 <3.0.0"
dart: ">=2.14.0 <3.0.0"
flutter: ">=2.5.0"

View File

@ -1,7 +1,7 @@
name: selfprivacy
description: selfprivacy.org
publish_to: 'none'
version: 0.4.2+10
version: 0.4.1+9
environment:
sdk: '>=2.13.4 <3.0.0'
@ -61,7 +61,6 @@ flutter:
- assets/images/
- assets/images/onboarding/
- assets/images/logos/
- assets/images/gifs/
- assets/translations/
- assets/markdown/
fonts: