1С: проверка пароля пользователя

Задача: проверить соответствие имени пользователю, введённый им пароль. Пользователи хранятся в стандартном справочнике «Пользователи»

Решение: в 1С нет штатных методов проверки пароля, т.к. пароль как таковой не хранится, а хранится его хэш. Следовательно для того чтобы проверить введенный пароль, необходимо сравнить «старый» хэш с хэшэм введеного пароля. Но есть нюанс — никто не знает по какому алгоритму генерируется хэш при сохранении пароля. Следовательно подходит лишь один алгоритм:

  1. Получаем хэш текущего пароля
  2. Начинаем транзакцию
  3. Сохраняем введеный пароль пароль у пользователя
  4. Получаем хэш введенного пароля
  5. Отменяем транзакцию (тем самым отменяем изменения у пользователя)
  6. Сравниваем первый хэш со вторым. Если равны — значит пароль соответствует.

Воплощение:

// Функция по входящим body.login и body.password выдает или error=true
// или возращает полное имя, уникальный идентификатор и список доступных для проведения инвентаризации документов
Функция Auth(body)
    answer = Новый Структура("error, result",false,"");		
    ПользовательИнформационнойБазы = ПользователиИнформационнойБазы.НайтиПоИмени(body.login);
	Если ПользовательИнформационнойБазы = Неопределено Тогда
    	answer.error=true;
		answer.result="Пользователь не найден в БД";
		возврат answer;
	Иначе
			ХэшНастоящегоПароля = ПользовательИнформационнойБазы.СохраняемоеЗначениеПароля;
			НачатьТранзакцию();		    
		    ПользовательИнформационнойБазы.Пароль = body.password;
		    ПользовательИнформационнойБазы.Записать();		    
		    ХешВведенногоПароля = ПользователиИнформационнойБазы.НайтиПоИмени(body.login).СохраняемоеЗначениеПароля;
		    ОтменитьТранзакцию();
		                                      
		    Если ХешВведенногоПароля = ХэшНастоящегоПароля Тогда
		        answer.error=false;
				answer.result=Новый Структура("UserName,UserId,MyInvent",ПользовательИнформационнойБазы.ПолноеИмя,ПользовательИнформационнойБазы.УникальныйИдентификатор,Новый Массив());
		    Иначе
				answer.error=true;
				answer.result="Не верный пароль пользователя";
				возврат answer;
		    КонецЕсли;	
	конецесли;
 возврат answer;                   
КонецФункции	

Flutter: уведомления

Для Flutter существуют несколько пакетов для отображения уведомлений. Я использую flutter_easyloading, т.к. в нём по мимо собственно различного вида уведомлений, добавлена и анимация прогресбара. Который можно например использовать при загрузке сетевых запросов.

Установка в pubspec.yaml:

dependencies:
  flutter_easyloading: ^3.0.5

Пример использования:

import 'package:flutter_easyloading/flutter_easyloading.dart';
...

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        builder: EasyLoading.init(),
....
                        onPressed: (){
                          EasyLoading.show(status: 'loading...');
                          http.post(Uri.parse('https://кацукацуhp'),body: {'login':_controller1.text,'password':_controller2.text}).then((response) {
....
EasyLoading.dismiss();

Есть и некая кастомизация:

void configLoading() {
  EasyLoading.instance
    ..displayDuration = const Duration(milliseconds: 2000)
    ..indicatorType = EasyLoadingIndicatorType.fadingCircle
    ..loadingStyle = EasyLoadingStyle.dark
    ..indicatorSize = 45.0
    ..radius = 10.0
    ..progressColor = Colors.yellow
    ..backgroundColor = Colors.green
    ..indicatorColor = Colors.yellow
    ..textColor = Colors.yellow
    ..maskColor = Colors.blue.withOpacity(0.5)
    ..userInteractions = true
    ..dismissOnTap = false
    ..customAnimation = CustomAnimation();
}

Flutter: работа с WebSocket

Получение данных по протоколу http/http как уже описывал это конечно хорошо, НО! обмен «онлайн» гораздо интереснее. Чтобы сервер в любой момент мог отправить информацию в приложение. И есть решение: при запуске приложения устанавливать соединен с сервером Websocket и дальше уже обменивать информацией по этому протоколу.

Пакет:

dependencies:
  web_socket_channel: ^2.2.0

Пример кода:

import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/status.dart' as status;
import 'dart:convert';
import 'dart:core';

void main() async {

  final channel = await IOWebSocketChannel.connect('ws://укау.цукац.ru:45500',pingInterval: Duration(seconds: 1));

  channel.stream.listen((message) {
    Map<String, dynamic> msg = jsonDecode(message);
     if (msg["command"]=="who_are_you"){
       channel.sink.add('{"command":"who_am_i","user":"10","type":"user"}');
     };
  });

...

Flutter: полноэкранный режим

В ранних версиях Flutter (до 3), полноэкранный режим приложения можно было выставить при помощи пакета Utils. Теперь же одним из вариантов может быть или пакет window_manager:

 WidgetsFlutterBinding.ensureInitialized();
  // Must add this line.
  await windowManager.ensureInitialized();

  // Use it only after calling hiddenWindowAtLaunch
  windowManager.waitUntilReadyToShow().then((_) async{
    // Hide window title bar
    await windowManager.setFullscreen(true);
  });

Или при помощи Flamer:

WidgetsFlutterBinding.ensureInitialized();
  await Flame.device.fullScreen();
  await Flame.device.setLandscape();

Однако ни тот ни другой способ не работают под Windows. Посему вопрос остается открытым..

Flutter: виджет Card

Данный виджет предназначен для того чтобы отобразить что-то в отдельной области «с тенью».

Например:

import 'package:flutter/material.dart';
import 'package:invent/globals.dart' as globals;

class TMCView extends StatefulWidget {
  _TMCViewState createState() => _TMCViewState(); // сюда передаем текущее состояние страницы
}
class _TMCViewState extends State<TMCView> {// _ впереди класса, означает чтоб скрыть доступ из другх файлов
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Найденое ТМЦ')),
      body: Center(
          child: Card (
            margin: EdgeInsets.all(10),
            color: Colors.green[100],
            shadowColor: Colors.blueGrey,
            elevation: 20,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: Image.network(
                    'https://picsum.photos/seed/49/600',
                    width: 100,
                    height: 100,
                    fit: BoxFit.cover,
                  ),
                  title: Text(
                    "Принтер",
                    style: TextStyle(fontSize: 20),
                  ),
                  subtitle: Text('Хороший принтер, нужно брать..'),
                ),
                ButtonBar(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: new Text('Добавить в найденые'),
                        onPressed: (){
                          Navigator.pushNamed(context, "/");
                        },
                      ),
                    ]

                ),
              ],
            ),
          )
      ),
    );
  }
}

Получим:

1 66 67 68 69 70 308