EExcel 丞燕快速查詢2

EExcel 丞燕快速查詢2
EExcel 丞燕快速查詢2 https://sandk.ffbizs.com/

Ory Hydra Authorization Code Exchange => access token

Before posts about Hydra get access token is use golang HydraOauthConfig.Exchange(ctx, code). This is easy way. But on front website like vue or other framework how to get access token.

Use REST Client to test



POST https://openid.hydra:9001/oauth2/token
Authorization: Basic YXV0aC1jb2RlLWNsaWVudDpzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=cuNw76aEuckIJJyVssk2LJvqdLXffT-8Kx1s0tYFt6Y.v0Dxc2_yT9ga8c2moKx0fDbwRFVgwryAt5BJM7lOJlM
#&redirect_uri=https://certfront/oid/test/callback
#&scope=openid,offline
#&client_id=auth-code-client
#&code_verifier=
#&state=gczxkznmjkrksgytsemvwgkf

Import is: Authorization: Basic


https://github.com/ory/hydra/issues/631

Not Authorization: Bearer


base64(urlencode(client_id):urlencode(client_secret))


YXV0aC1jb2RlLWNsaWVudDpzZWNyZXQ= => auth-code-client:secret


code is callback code. When you login-consent finish step then callback to your set callback URL. Watch URL inside have code=


example: https://t.tt:9010/callback?code=cuNw76aEuckIJJyVssk2LJvqdLXffT-8Kx1s0tYFt6Y.v0Dxc2_yT9ga8c2moKx0fDbwRFVgwryAt5BJM7lOJlM&scope=openid%20offline&state=gczxkznmjkrksgytsemvwgkf

If code have error message, you need check before any step have incorrect.


In Ory Hydra get access token is not like sdk document


https://www.ory.sh/docs/hydra/sdk/api#the-oauth-20-token-endpoint

You need to sure grant_type=authorization_code Not other options.

But SDK Document No any options example. Only suggestion you use lib. So you need to try many.

like follow
https://www.oauth.com/oauth2-servers/pkce/authorization-code-exchange/
https://community.ory.sh/t/how-configure-grant-implicit-flow/411/14
https://auth0.com/docs/api-auth/tutorials/authorization-code-grant-pkce
https://github.com/oauthjs/express-oauth-server/issues/55
https://www.jianshu.com/p/5cf2b7a45b75
http://www.passportjs.org/docs/oauth/

Then try out a ways.

OK. Mark is not important Required.


#&redirect_uri=https://certfront/oid/test/callback
#&scope=openid,offline
#&client_id=auth-code-client
#&code_verifier=
#&state=gczxkznmjkrksgytsemvwgkf

oauth2 nodejs

https://peach.ebu.io/technical/tutorials/tuto-oauth2-client/

https://www.pveller.com/oauth2-with-passport-10-steps-recipe/

http://www.hitotec.com/authentification-oauth-avec-passportjs-pour-une-api-rest/


https://www.shangyang.me/2018/03/11/javascript-nodejs-passport-04-deepinto-oauth2-authenticate-process/

https://blog.yorkxin.org/2013/09/30/oauth2-4-1-auth-code-grant-flow.html

[轉]如何使用 OpenSSL 建立開發測試用途的自簽憑證 (Self-Signed Certificate)

https://blog.miniasp.com/post/2019/02/25/Creating-Self-signed-Certificate-using-OpenSSL



目前這個方式比較靠普


建立 ssl.conf 設定檔


[req]
prompt = no
default_md = sha256
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_req

[dn]
C = TW
ST = Taiwan
L = Taipei
O = Duotify Inc.
OU = IT Department
emailAddress = admin@example.com
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.localhost
DNS.2 = localhost
DNS.3 = 192.168.2.100


openssl req -x509 -new -nodes -sha256 -utf8 -days 3650 -newkey rsa:2048 -keyout server.key -out server.crt -config ssl.conf

oauth2 nodejs vue

https://www.ory.sh/docs/hydra/integration#interacting-with-oauth-20

https://github.com/lelylan/simple-oauth2

https://www.jianshu.com/p/5cf2b7a45b75

windows iso

http://windowsiso.net/

vue 3 image assets

Vue template Code


src/ooxx/ooxx/xx.vue

assets


File location:assets/img/tt.png

OK

Code:
img src='@/assets/img/tt.png'

Become:
img src="/img/tt.f3b936ef.png"


Failed

Code:
img src='@/img/nchcbclab.png'

img src='assets/img/tt.png'
img src='./assets/img/tt.png'
img src='../assets/img/tt.png'

img src="require('assets/img/tt.png') "
img src="require('./assets/img/tt.png') "
img src="require('../assets/img/tt.png') "



public


File location:public/img/tt.png

OK

Code:
img src= '/img/nchcbclab.png'

Become:
img src= '/img/nchcbclab.png'


Failed

Code:
img src= 'img/nchcbclab.png'

img src= 'public/img/nchcbclab.png'
img src='/public/img/nchcbclab.png'

vue 3 index.html

old vue index.html just copy to public directory.

If public don't have index.hmtl, be craeted by run "npm run serve". But public don't have index.html.
Only "npm run build" create index.html in dist driectory.

More easy understand way:


You delete all project index.html. This time still can run "npm run serve". Watch Website source code <title>Vue App</title>

Then put your custome into public directory then <title>Custome App ooxxooxx </title>

vue babel 7

https://github.com/storybookjs/storybook/issues/5298
https://github.com/webpack/webpack/issues/4039
https://github.com/gmfe/Think/issues/67

Cannot assign to read only property 'exports' of object '#<Object>'


babel.config.js



 'sourceType': 'unambiguous', // 自动推断编译的模块类型(cjs,es6)
 'ignore': [/@babel[/\\]runtime/], // 忽略 @babel/runtime

Full code

module.exports = {
  'sourceType': 'unambiguous', // 自动推断编译的模块类型(cjs,es6)
  'ignore': [/@babel[/\\]runtime/], // 忽略 @babel/runtime
  presets: [
    '@vue/app'
  ]
}

vue 3 vue-cli-service serve vue.config.js package.json docker

"serve": "vue-cli-service serve",

Some page modify vue-cli-service serve --host 0.0.0.0 --port 8978

This may in docker failed.

Error: listen EADDRNOTAVAIL: address not available


So some page modify vue.config.js

Use public is Failed!!

    devServer: {
        public: '0.0.0.0:80', 
        disableHostCheck: true,
    }


Use host port is Correct!!

module.exports = {
    chainWebpack: config => {
        config.module.rules.delete('eslint');
    },
    devServer: {
        host: '0.0.0.0',
        port: '80',
        //public: '0.0.0.0:80',  //無效
        disableHostCheck: true,
    }
}


PS:
.Put eslint is maybe get some eslint error, not about host ip port.
.disableHostCheck can remove for try by yourself env.

Mirror Your Traffic Duplicate

goreplay
https://github.com/buger/goreplay

tcpcopy
https://github.com/session-replay-tools/tcpcopy

teeproxy
https://github.com/chrislusf/teeproxy

duplicator
https://github.com/agnoster/duplicator

goduplicator
https://github.com/mkevac/goduplicator

nginx mirror

haproxy mirror

[轉]How to Mirror Your Traffic with Nginx

https://www.serverlab.ca/tutorials/linux/web-servers-linux/how-to-mirror-your-traffic-with-nginx/

Mirror Your Traffic

ngnix mirror

ipfs

https://www.fil.club/view/77.html

端口8080是HTTP网关,它允许您使用浏览器查询ipfs数据(请参阅此示例)
端口4001是IPFS用于与其他节点通信的群集端口,端口5001用于本地API。
我们5001只会绑定127.0.0.1因为它不应该暴露给外界。


我们已经安装了数据和分段卷。

该data卷用于存储IPFS本地存储(配置和数据库),并且
staging是一个可用于暂存文件以供命令行使用的目录(例如ipfs add)。

如果您只使用API,则可以省略暂存目录卷。当然,随意将这些目录放在除了之外的其他地方/tmp。

[轉]用Go来做以太坊开发

https://github.com/miguelmota/ethereum-development-with-go-book

https://goethereumbook.org/zh/

ethereum explorer

https://github.com/gobitfly/etherchain-light
https://github.com/gobitfly/erc20-explorer

https://github.com/carsenk/explorer


https://github.com/Capgemini-AIE/ethereum-docker/tree/master/monitored-geth-client
https://github.com/cubedro/eth-net-intelligence-api
https://github.com/cubedro/eth-netstats

Browse blocks and transactions
It's nice to have some simple analogue of Etherscan for your local chain browsing. It will be useful to examine transactions, balances, blocks and etc. It appeared that it is quite difficult to find an open-source good solution for geth. After several tries I found an acceptable solution called ETHExplorer V2. Clone it into explorer-v2 folder. To Dockerize it I had to make 2 changes. First create a Dockerfile


# ./explorer-v2/Dockerfile
FROM node:6
 
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm install && \
    node_modules/.bin/bower install --allow-root

And change start script in package.json to "start": "http-server ./app -a 0.0.0.0 -p 8000 -c-1". This is required to allow connections to explorer from any IP (outside docker). Next we should create a service for explorer


 ./docker-compose.yml
# ...
explorer:
    build: explorer-v2
    container_name: explorer
    command: npm start
    ports:
        - "8000:8000"

nestjs csrf

https://gitissue.com/repos/jiayisheji/blog

pass csrf https://github.com/expressjs/csurf/issues/21

main.ts



import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path'
import { AppModule } from './app.module';
import * as cookieSession from 'cookie-session';
import * as helmet from 'helmet';
import * as cookieParser from 'cookie-parser';
import * as csurf from 'csurf';
import * as rateLimit from 'express-rate-limit';

async function bootstrap() {
  const app = await NestFactory.create(
    AppModule,
  );

  app.init()
  
  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  app.setViewEngine('pug');

  app.set('trust proxy', 1);

  app.use(cookieSession({
    name: 'session',
    keys: ['key1', 'key2']
  }));

  //app.enableCors();
  app.use(helmet());
  app.use(cookieParser());
  //app.use(csurf({ cookie: true }));  //正常是這行,但有些API POST時需要略過csrf
  app.use(function (req, res, next) {
    var mw = csurf({ cookie: true });
    // console.log(req.url)  // check real get url
    if (req.url === '/testpostcsrf') return next();  //pass csrf check
    mw(req, res, next);
  });
  app.use(
    rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100, // limit each IP to 100 requests per windowMs
    }),
  );

  await app.listen(3000);
}
bootstrap();


layout.pug



doctype html
html
  head
    title= title
    meta(content= csrfToken, name='csrf-token')
  body
    block content

login.pug



extends layout

block content
    h1 Please log in
    if error
        p.
            #{error}
    form(action="/login",method="POST")
        input(type="hidden",name="_csrf",value=csrfToken)
        input(type="hidden",name="challenge",value=challenge)
        table(style="")
            tr
                td
                    input(type="email",id="email",name="email",placeholder="email@foobar.com")
                td.
                    (Example: "foo@bar.com")
            tr
                td
                    input(type="password",id="password",name="password")
                td.
                    (Example: "foobar")
        input(type="checkbox",id="remember",name="remember",value="1")
        label(for="remember") Remember me
        br
        input(type="submit",id="accept",value="Log in")




nest.js 让我们用Nestjs来重写一个CNode

https://gitissue.com/repos/jiayisheji/blog

這網站中的 让我们用Nestjs来重写一个CNode(上、中、下) 幫了大忙,減少大量的浪費時間

===========
html -> jade/pug
http://html2jade.aaron-powell.com/

when you html meta want to become jade/pug

layout.pug

meta(content= csrfToken, name='csrf-token')

nodejs expressjs

https://expressjs.com/en/advanced/best-practice-security.html

OpenID hydra docker-compose hydra-login-consent-node mariadb


docker-compose


version: '3.3'

services:
  ory-hydra-postgres:
    image: postgres:9.6
    #restart: always
    environment:
      - POSTGRES_USER=hydra
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=hydra
    volumes:
      - hydradata:/var/lib/postgresql/data:rw
    networks:
      - openid
  # 第一次執行postgres要做資料庫格式建立 PS: network依佈屬環境為主 docker network ls 確認
  # docker run -it --rm \
  #   --network openid \
  #   oryd/hydra:latest \
  #   migrate sql --yes postgres://hydra:secret@ory-hydra-postgres:5432/hydra?sslmode=disable
  
  ory-hydra:
    image: oryd/hydra:latest
    restart: unless-stopped
    ports:
      - "9001:4444"
      - "9002:4445"
    environment:
      - SECRETS_SYSTEM=this_needs_to_be_the_same_a
      - DSN=postgres://hydra:secret@ory-hydra-postgres:5432/hydra?sslmode=disable
      - URLS_SELF_ISSUER=https://openid.hydra:9001/
      - URLS_CONSENT=http://192.168.99.100:9020/consent
      - URLS_LOGIN=http://192.168.99.100:9020/login
      - LOG_LEVEL=debug
      - OAUTH2_EXPOSE_INTERNAL_ERRORS=true
      - SERVE_PUBLIC_CORS_ENABLED=true
      - SERVE_PUBLIC_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE
      - SERVE_ADMIN_CORS_ENABLED=true
      - SERVE_ADMIN_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE
      - SERVE_TLS_KEY_BASE64=LS0tLS1CRUdJTiBFQyBQQVJBTUVURVJTLS0tLS0KQmdVcmdRUUFJZz09Ci0tLS0tRU5EIEVDIFBBUkFNRVRFUlMtLS0tLQotLS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUlHa0FnRUJCRENLbkdnVnFJVzdZaW5iUWV5UEd5UTQ0R3U2VVFEelU5SENLYjMzTWlmeFJYRTBkbnU2KzdadQowdEJUcUhQRHVMeWdCd1lGSzRFRUFDS2haQU5pQUFSbng1Nk9jeGNyRWRsYmU4TXRSdUVxWGV2OEREcmh6ZWJGCjM4NlI4Q2RQWDRlUWI2Zll6ekFUL3V3STBsTDdvRmlEWEM3Q0JLWmZUcTdFSzN4TzNXWlpSSjJrMEQ3TnNLd2cKVEpZenJxT0JpczBNeGtva2FUWVVyemhKMXBKY3lmWT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
      - SERVE_TLS_CERT_BASE64=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNQVENDQWNLZ0F3SUJBZ0lKQU13RjRiVDRvSnh0TUFvR0NDcUdTTTQ5QkFNQ01Gd3hDekFKQmdOVkJBWVQKQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbgphWFJ6SUZCMGVTQk1kR1F4RlRBVEJnTlZCQU1NREc5d1pXNXBaQzVvZVdSeVlUQWVGdzB4T1RBMk1UY3dNVEl4Ck16ZGFGdzB5T1RBMk1UUXdNVEl4TXpkYU1Gd3hDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWwKTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhGVEFUQmdOVgpCQU1NREc5d1pXNXBaQzVvZVdSeVlUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkdmSG5vNXpGeXNSCjJWdDd3eTFHNFNwZDYvd01PdUhONXNYZnpwSHdKMDlmaDVCdnA5alBNQlArN0FqU1V2dWdXSU5jTHNJRXBsOU8KcnNRcmZFN2RabGxFbmFUUVBzMndyQ0JNbGpPdW80R0t6UXpHU2lScE5oU3ZPRW5Xa2x6SjlxTlFNRTR3SFFZRApWUjBPQkJZRUZHK3Z6ZkIxYmVnM1VadEpYRXZWOWRNa1hvNmdNQjhHQTFVZEl3UVlNQmFBRkcrdnpmQjFiZWczClVadEpYRXZWOWRNa1hvNmdNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURhUUF3WmdJeEFMUHYKODZFSFRUVElLcEJHdlQrY2NWN3djSC84SFIrc2xhZC9ZUFhLUlZwd2RDbzUyZVRPV3BDS2dGamtHNEJhd1FJeApBTGxGZFgwbEk2ZzhXS3lhRTVmKzJGZEkxYWVqQ0Ftd0xPTTZTRFJhNFVHbitDa2VwOEljeG1CTDIvQmUzSVZ6CjhnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    networks:
      - openid


# 快速建立 auth-doce-client PS: network依佈屬環境為主 docker network ls 確認
#docker run --rm -it \
#  -e HYDRA_ADMIN_URL=https://ory-hydra:4445 \
#  --network openid \
#  oryd/hydra:latest \
#  clients create --skip-tls-verify \
#    --id auth-code-client \
#    --secret secret \
#    --grant-types authorization_code,refresh_token \
#    --response-types code,id_token,token \
#    --scope openid,offline,photos.read \
#    --callbacks https://t.tt:9010/callback

  ory-hydra-login-consent:
    #image: oryd/hydra-login-consent-node:latest
    build:
      context: hydra-login-consent-node/
    restart: unless-stopped
    ports:
      - "9020:3000"
    environment:
      - HYDRA_ADMIN_URL=https://ory-hydra:4445
      - NODE_TLS_REJECT_UNAUTHORIZED=0
    volumes:
      - hydraloginconsent:/usr/src/app:rw
    depends_on:
      - mariadb
    networks:
      - openid
  
  mariadb:
    image: mariadb:10.4.6
    #restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=openid
    command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
    #第一次使執行db_init_sql.txt
    networks:
      - openid

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
    depends_on:
      - mariadb
    networks:
      - openid

volumes:  
  hydradata: 
  hydraloginconsent:
    
networks:
  openid:
    driver: bridge


Use adminer test maraidb: http://192.168.99.100:8080 root/secret


mariadb init


DROP DATABASE IF EXISTS `openid`;
CREATE DATABASE `openid` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
USE `openid`;

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `password` text COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `user` (`id`, `name`, `email`, `password`) VALUES
(1, 'foobar', 'foo@bar.com', '3858f62230ac3c915f300c664312c63f');

ory-hydra-login-consent modify package.json add


"md5": "^2.2.1",
"mysql": "^2.17.1"

ory-hydra-login-consent add db/database.js


var mysql = require('mysql');

var pool = mysql.createPool({
  host     : 'mariadb',
  user     : 'root',
  password : 'secret',
  database: 'openid'
});

var query=function(sql,options,callback){  
  pool.getConnection(function(err,conn){  
    pool.query
    if(err){  
      callback(err,null,null);  
    }else{  
      conn.query(sql,options,function(err,results,fields){  
        //释放连接  
        conn.release();  
        //事件驱动回调  
        callback(err,results,fields);  
      });  
    }  
  });  
}; 

module.exports = {query, pool}

ory-hydra-login-consent modify routes/login.js


...

router.post('/', csrfProtection, function (req, res, next) {
  // The challenge is now a hidden input field, so let's take it from the request body instead
  var challenge = req.body.challenge;

  var sql = "select count(*) as count from user where email = ? and password = ?"
  var params = [req.body.email, md5(req.body.password)]
  //db.get(sql, params, (err, row) => {
  pool.query(sql, params, (err, row) => {
    if (err) {
      res.status(400).json({"db error":err.message});
      return;
    }

    if(!(row.count==1)){ //找不到
      res.render('login', {
        csrfToken: req.csrfToken(),
  
        challenge: challenge,
  
        error: 'The username / password combination is not correct'
      });
      return;
    }

    hydra.acceptLoginRequest(challenge, {
      // Subject is an alias for user ID. A subject can be a random string, a UUID, an email address, ....
      subject: req.body.email,
  
      // This tells hydra to remember the browser and automatically authenticate the user in future requests. This will
      // set the "skip" parameter in the other route to true on subsequent requests!
      remember: Boolean(req.body.remember),
  
      // When the session expires, in seconds. Set this to 0 so it will never expire.
      remember_for: 3600,
  
      // Sets which "level" (e.g. 2-factor authentication) of authentication the user has. The value is really arbitrary
      // and optional. In the context of OpenID Connect, a value of 0 indicates the lowest authorization level.
      // acr: '0',
    })
    .then(function (response) {
      // All we need to do now is to redirect the user back to hydra!
      res.redirect(response.redirect_to);
    })
    // This will handle any error that happens when making HTTP calls to hydra
    .catch(function (error) {
      next(error);
    });

  });

  // Let's check if the user provided valid credentials. Of course, you'd use a database or some third-party service
  // for this!
  // if (!(req.body.email === 'foo@bar.com' && req.body.password === 'foobar')) {
  //   // Looks like the user provided invalid credentials, let's show the ui again...

  //   res.render('login', {
  //     csrfToken: req.csrfToken(),

  //     challenge: challenge,

  //     error: 'The username / password combination is not correct'
  //   });
  //   return;
  // }

  // Seems like the user authenticated! Let's tell hydra...
  // hydra.acceptLoginRequest(challenge, {
  //   // Subject is an alias for user ID. A subject can be a random string, a UUID, an email address, ....
  //   subject: 'foo@bar.com',

  //   // This tells hydra to remember the browser and automatically authenticate the user in future requests. This will
  //   // set the "skip" parameter in the other route to true on subsequent requests!
  //   remember: Boolean(req.body.remember),

  //   // When the session expires, in seconds. Set this to 0 so it will never expire.
  //   remember_for: 3600,

  //   // Sets which "level" (e.g. 2-factor authentication) of authentication the user has. The value is really arbitrary
  //   // and optional. In the context of OpenID Connect, a value of 0 indicates the lowest authorization level.
  //   // acr: '0',
  // })
  //   .then(function (response) {
  //     // All we need to do now is to redirect the user back to hydra!
  //     res.redirect(response.redirect_to);
  //   })
  //   // This will handle any error that happens when making HTTP calls to hydra
  //   .catch(function (error) {
  //     next(error);
  //   });

  // You could also deny the login request which tells hydra that no one authenticated!
  // hydra.rejectLoginRequest(challenge, {
  //   error: 'invalid_request',
  //   error_description: 'The user did something stupid...'
  // })
  //   .then(function (response) {
  //     // All we need to do now is to redirect the browser back to hydra!
  //     res.redirect(response.redirect_to);
  //   })
  //   // This will handle any error that happens when making HTTP calls to hydra
  //   .catch(function (error) {
  //     next(error);
  //   });
});

https://t.tt:9010 When login id/pwd, can use adminer change database user email/password.

OpenID hydra docker-compose


docker-compose

version: '3.3'

services:
  ory-hydra-postgres:
    image: postgres:9.6
    #restart: always
    environment:
      - POSTGRES_USER=hydra
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=hydra
    volumes:
      - hydradata:/var/lib/postgresql/data:rw
    networks:
      - openid

# 第一次執行postgres要做資料庫格式建立 PS: network依佈屬環境為主 docker network ls 確認
# docker run -it --rm \
#   --network openid \
#   oryd/hydra:latest \
#   migrate sql --yes postgres://hydra:secret@ory-hydra-postgres:5432/hydra?sslmode=disable

  ory-hydra:
    image: oryd/hydra:latest
    restart: unless-stopped
    ports:
      - "9001:4444"
      - "9002:4445"
    environment:
      - SECRETS_SYSTEM=this_needs_to_be_the_same_a
      - DSN=postgres://hydra:secret@ory-hydra-postgres:5432/hydra?sslmode=disable
      - URLS_SELF_ISSUER=https://openid.hydra:9001/
      - URLS_CONSENT=http://192.168.99.100:9020/consent
      - URLS_LOGIN=http://192.168.99.100:9020/login
      - LOG_LEVEL=debug
      - OAUTH2_EXPOSE_INTERNAL_ERRORS=true
      - SERVE_PUBLIC_CORS_ENABLED=true
      - SERVE_PUBLIC_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE
      - SERVE_ADMIN_CORS_ENABLED=true
      - SERVE_ADMIN_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE
      - SERVE_TLS_KEY_BASE64=LS0tLS1CRUdJTiBFQyBQQVJBTUVURVJTLS0tLS0KQmdVcmdRUUFJZz09Ci0tLS0tRU5EIEVDIFBBUkFNRVRFUlMtLS0tLQotLS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUlHa0FnRUJCRENLbkdnVnFJVzdZaW5iUWV5UEd5UTQ0R3U2VVFEelU5SENLYjMzTWlmeFJYRTBkbnU2KzdadQowdEJUcUhQRHVMeWdCd1lGSzRFRUFDS2haQU5pQUFSbng1Nk9jeGNyRWRsYmU4TXRSdUVxWGV2OEREcmh6ZWJGCjM4NlI4Q2RQWDRlUWI2Zll6ekFUL3V3STBsTDdvRmlEWEM3Q0JLWmZUcTdFSzN4TzNXWlpSSjJrMEQ3TnNLd2cKVEpZenJxT0JpczBNeGtva2FUWVVyemhKMXBKY3lmWT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
      - SERVE_TLS_CERT_BASE64=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNQVENDQWNLZ0F3SUJBZ0lKQU13RjRiVDRvSnh0TUFvR0NDcUdTTTQ5QkFNQ01Gd3hDekFKQmdOVkJBWVQKQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbgphWFJ6SUZCMGVTQk1kR1F4RlRBVEJnTlZCQU1NREc5d1pXNXBaQzVvZVdSeVlUQWVGdzB4T1RBMk1UY3dNVEl4Ck16ZGFGdzB5T1RBMk1UUXdNVEl4TXpkYU1Gd3hDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWwKTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhGVEFUQmdOVgpCQU1NREc5d1pXNXBaQzVvZVdSeVlUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkdmSG5vNXpGeXNSCjJWdDd3eTFHNFNwZDYvd01PdUhONXNYZnpwSHdKMDlmaDVCdnA5alBNQlArN0FqU1V2dWdXSU5jTHNJRXBsOU8KcnNRcmZFN2RabGxFbmFUUVBzMndyQ0JNbGpPdW80R0t6UXpHU2lScE5oU3ZPRW5Xa2x6SjlxTlFNRTR3SFFZRApWUjBPQkJZRUZHK3Z6ZkIxYmVnM1VadEpYRXZWOWRNa1hvNmdNQjhHQTFVZEl3UVlNQmFBRkcrdnpmQjFiZWczClVadEpYRXZWOWRNa1hvNmdNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURhUUF3WmdJeEFMUHYKODZFSFRUVElLcEJHdlQrY2NWN3djSC84SFIrc2xhZC9ZUFhLUlZwd2RDbzUyZVRPV3BDS2dGamtHNEJhd1FJeApBTGxGZFgwbEk2ZzhXS3lhRTVmKzJGZEkxYWVqQ0Ftd0xPTTZTRFJhNFVHbitDa2VwOEljeG1CTDIvQmUzSVZ6CjhnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    networks:
      - openid
    #這行非常重要,docker成功運行後,要進geht console執行 admin.addPeer("enode://444a16729d32431bbdaa594272e3509cdeaaf3c995ffb583589163d35f8b36ad14394ab037ac186525f579700e6500cacfb1f953fdf066fa05da0e1d409f7f79@140.110.18.199:30301")

  ory-hydra-login-consent:
    #image: oryd/hydra-login-consent-node:latest
    build:
      context: hydra-login-consent-node/
    restart: unless-stopped
    ports:
      - "9020:3000"
    environment:
      - HYDRA_ADMIN_URL=https://ory-hydra:4445
      - NODE_TLS_REJECT_UNAUTHORIZED=0
    volumes:
      - hydraloginconsent:/usr/src/app:rw
    networks:
      - openid

# 快速建立 auth-doce-client PS: network依佈屬環境為主 docker network ls 確認
#docker run --rm -it \
#  -e HYDRA_ADMIN_URL=https://ory-hydra:4445 \
#  --network openid \
#  oryd/hydra:latest \
#  clients create --skip-tls-verify \
#    --id auth-code-client \
#    --secret secret \
#    --grant-types authorization_code,refresh_token \
#    --response-types code,id_token,token \
#    --scope openid,offline,photos.read \
#    --callbacks https://t.tt:9010/callback

volumes:  
  hydradata: 
  hydraloginconsent:
    
networks:
  openid:
    driver: bridge

ory-hydra-login-consent download

https://github.com/ory/hydra-login-consent-node
Directory name is hydra-login-consent-node


go run main.go

https://sueboy.blogspot.com/2019/06/openid-hydra-cant-finish-error.html


Broswer https://t.tt:9010

9-HyperLedger-Fabric原理-MSP详解(一)-MSP基础

https://zhuanlan.zhihu.com/p/35683522

Helm charts for running and operating Hyperledger Fabric in Kubernetes

https://github.com/apggroeifabriek/pivt

hyperledger crypetogen

https://hyperledger-fabric.readthedocs.io/en/release-1.4/commands/cryptogen.html

cryptogen is an utility for generating Hyperledger Fabric key material. It is provided as a means of preconfiguring a network for

testing purposes

. It would normally not be used in the operation of a production network.

Firebase auth and upload image

bootstrap + web firebase realtime + firebase storage

Auth:Use Email&password then input one user with email & password. Login use be added user.

index.html


<!doctype html>
<html lang="zh-Hant-TW">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.css" />

    <title>Hello, world!</title>
  </head>
  <body>
    <div class="container">
        <div id="firebaseui-auth-container" class="alert alert-light" role="alert"></div>
    </div>
    
    <div class="container my-1">
        <div class="row">
            <div class="col-sm">Login Status
                <div class="user-signed-in" style="display: none;"><span class="badge badge-pill badge-success">user-signed-in</span></div>
                <div class="user-signed-out" style="display: none;"><span class="badge badge-pill badge-secondary">user-signed-out</span></div>
            </div>
            <div class="col-sm"><a class="btn btn-outline-primary" data-toggle="collapse" href="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Account Details</a>
                <div class="collapse multi-collapse" id="multiCollapseExample1">
                    <div class="card card-body">
                        <pre id="account-details">...</pre>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="container my-1">
        <div class="row justify-content-end">
            <div class="col-2">
                <div id="sign-in" class="btn btn-outline-primary" style="display: none;">sign-in</div>
                <div id="sign-out" class="btn btn-outline-danger" style="display: none;">sign-out</div>
            </div>
        </div>
    </div>

    <div class="container my-1">
        <div class="row justify-content-center">
            <div id="loading" class="spinner-border" role="status">
                <span class="sr-only">Loading...</span>
            </div>
        </div>
    </div>
    
    <div class="container my-1">
        <div id="loaded" class="user-signed-in" style="display: none;">檔案上傳
            <div id="filesubmit">
                <input type="file" class="file-select" accept="image/*"/>
                <button class="file-submit">SUBMIT</button>
            </div>
        </div>
    </div>

    <div class="container my-1">
        <div class="row">
            <div class="col-2">
                <div id="test" class="btn btn-outline-primary">test</div>
            </div>
        </div>
    </div>
    
        <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <script src="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.js"></script>
    <script src="https://www.gstatic.com/firebasejs/ui/4.0.0/firebase-ui-auth__zh_tw.js"></script>

    <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-app.js"></script>
    <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-auth.js"></script>
    <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-database.js"></script>
    <!--<script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-firestore.js"></script>-->
    <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-storage.js"></script>
    
    <script defer src="./init-firebase.js"></script>
    <script>
        
    </script>
    <script>
        document.getElementById('test').addEventListener('click', function() {
            var fbdbpath = getfbdbPath('images/@/default/');
            putimageurl(fbdbpath, 'url');
        });
        
        function fileupload(){ //== File upload ========================
            document.querySelector('.file-select').addEventListener('change', handleFileUploadChange);
            document.querySelector('.file-submit').addEventListener('click', handleFileUploadSubmit);
            
            let selectedFile;

            function handleFileUploadChange(e) {
                selectedFile = e.target.files[0];
            }

            function handleFileUploadSubmit(e) {
                var metadata = {
                    contentType: 'image/jpeg'
                };

                var fbdbpath = getfbdbPath('images/@/default/');
                var newfbdbPostKey= getfbdbPostKey(fbdbpath);
                var uploadTask = imagesRef.child(`${newfbdbPostKey}`).put(selectedFile, metadata);

                uploadTask.on('state_changed', function(snapshot){
                    var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
                    console.log('Upload is ' + progress + '% done');
                    switch (snapshot.state) {
                        case firebase.storage.TaskState.PAUSED: // or 'paused'
                        console.log('Upload is paused');
                        break;
                        case firebase.storage.TaskState.RUNNING: // or 'running'
                        console.log('Upload is running');
                        break;
                    }
                    }, function(error) {
                        // Handle unsuccessful uploads
                        alert('Upload is Failed;');
                        console.log(error);
                    }, function() {
                        uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
                            console.log('File available at', downloadURL);
                            putimageurl(fbdbpath, downloadURL);
                        });
                    }
                );
            }
        }


        function initsign(){ //== Auth ===============================
            document.getElementById('sign-in').addEventListener('click', function() {
                if($('.user-signed-out').css('display') === 'block') ui.start('#firebaseui-auth-container', getUiConfig());
            });

            document.getElementById('sign-out').addEventListener('click', function() {
                var user = firebase.auth().currentUser;

                if (user) {
                    firebase.auth().signOut().then((res)=>{
                        console.log('signOut ok', res);
                    }).catch((err)=>{
                        alert('Logout Failed!');
                        console.warn('signOut error',res);
                    }).finally((res)=>{
                        console.log('signOut resolved', res);
                        location.reload();
                    });
                }
            });
        }

    </script>

  </body>
</html>


init-firebase.js


var firebaseConfig  = {
  apiKey: 'AIzaSyBxxxxxxooooo',
  authDomain: 'product-xxxxxxooooo.firebaseapp.com',
  databaseURL: 'https://product-xxxxxxooooo.firebaseio.com',
  storageBucket: 'gs://product-xxxxxxooooo.appspot.com'
};
firebase.initializeApp(firebaseConfig);

//== database ===========================
var database = firebase.database();

function getfbdbPath(type){
  var userId = firebase.auth().currentUser.uid;
  return type.replace("@", userId);
}

function getfbdbPostKey(path){
  return firebase.database().ref().child(path).push().key;
}

function putimageurl(path, url){
  //var userId = firebase.auth().currentUser.uid;
  var path = getfbdbPath('images/@/default/');
  var postImg = {
    active: true,
    url: url,
  };

  var newPostKey = getfbdbPostKey(path);
  var images = {};
  images[path + newPostKey] = postImg;
  //updates['/user-posts/' + userId + '/' + newPostKey] = postData;

  var uploadImagesResult = firebase.database().ref().update(images);
  console.log('uploadImagesResult');
  console.log(uploadImagesResult);
}

function test(){
  var userId = firebase.auth().currentUser.uid;

  firebase.database().ref('users/' + userId).set({
    username: 'name',
    email: 'email',
    profile_picture : 'imageUrl'
  }, function(error) {
    if (error) {
      console.log(error)
      // The write failed...
    } else {
      // Data saved successfully!
      console.log("successfullly!")
    }
  });

  var c = firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
    var username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
    // ...
    console.log("username:", username);
  });
  console.log('c');
  console.log(c);

  var postData = {
    author: 'username',
    uid: userId,
  };
  var newPostKey = firebase.database().ref().child('posts').push().key;
  var updates = {};
  updates['/posts/' + newPostKey] = postData;
  //updates['/user-posts/' + userId + '/' + newPostKey] = postData;
  //firebase.database().ref('posts/' + userId).set(postData);

  var t = firebase.database().ref().update(updates);
  console.log('t');
  console.log(t);
}


//== File upload ========================
var storageRef = firebase.storage().ref();
var imagesRef = storageRef.child('images');

// var otherProject = firebase.initializeApp(firebaseConfig, 'other');
// console.log(otherProject.name);    // "otherProject"
// var otherStorage = otherProject.storage();

//== Auth ===============================
function getUiConfig() {
  return {
    signInSuccessUrl: this.location.href,
    signInOptions: [
      firebase.auth.EmailAuthProvider.PROVIDER_ID,
    ],
    //immediateFederatedRedirect: false,
  };
}

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());
// The start method will wait until the DOM is loaded.
if (ui.isPendingRedirect()) {
  ui.start('#firebaseui-auth-container', getUiConfig());
}
// Disable auto-sign in.
// ui.disableAutoSignIn();

var handleSignedInUser = function(user) {
  $('.user-signed-in').show();
  $('.user-signed-out').hide();
  $('#sign-in').hide();
  $('#sign-out').show();
  document.getElementById('account-details').textContent = user.displayName;
  user.getIdToken().then(function(accessToken) {
    document.getElementById('account-details').textContent = 
      JSON.stringify({
        displayName: user.displayName,
        email: user.email,
        emailVerified: user.emailVerified,
        phoneNumber: user.phoneNumber,
        photoURL: user.photoURL,
        uid: user.uid,
        accessToken: user.accessToken,
        providerData: user.providerData
      }, null, '  ');
  });
};

var handleSignedOutUser = function() {
  $('.user-signed-in').hide();
  $('.user-signed-out').show();
  $('#sign-in').show();
  $('#sign-out').hide();
  //ui.start('#firebaseui-container', getUiConfig());
};

function handleConfigChange() {
  // Reset the inline widget so the config changes are reflected.
  ui.reset();
  ui.start('#firebaseui-container', getUiConfig());
}

firebase.auth().onAuthStateChanged(function(user) {
  document.getElementById('loading').style.display = 'none';
  document.getElementById('loaded').style.display = 'block';
  user ? handleSignedInUser(user) : handleSignedOutUser();
}, function(error) {
  console.log(error);
});

initsign();
fileupload();


firebase realtime database rule

95dWpHhg5wOk1loIj0iTneWdfwG2 is admin user <= userId = firebase.auth().currentUser.uid;

{
"rules": {
".read": "'95dWpHhg5wOk1loIj0iTneWdfwG2' === auth.uid",
"users": {
"$uid": {
".write": "$uid === auth.uid"
}
},
"images": {
".write": "'95dWpHhg5wOk1loIj0iTneWdfwG2' === auth.uid",
}
}
}


firebase storage rule

95dWpHhg5wOk1loIj0iTneWdfwG2 is admin user <= userId = firebase.auth().currentUser.uid;

rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
allow write: if '95dWpHhg5wOk1loIj0iTneWdfwG2' == request.auth.uid;
}
}
}

[轉]PoA private network clique: 😱 block lost

https://github.com/ethereum/go-ethereum/issues/18405

That's generally fine. The way clique works is that the in-turn sealer who should ideally sign next tries to sign and propagate the block immediately when the timer ticks. If no in-turn block appears within 500ms, the other signers start potentially creating alternative blocks (with random delays), this ensures that even if a signer is missing, the chain progresses more or less properly.

Now, if the original in-turn signer does come around and publish its block with some delay, that might reorg out alternative blocks signer by out-of-turn signers. At that point those will complain that their block was lost. The scary smiley is mostly meant for ethash :) Clique blocks have no subsidy anyway :)

How to use Makefile in docker-machine

https://stackoverflow.com/questions/34624510/how-to-use-makefile-in-docker-machine


tce-load -wi make

ethereum geth keystore -> private key -> address (check)

Use keythereum, web3


npm install keythereum
npm install web3


.datadir need to correct.
UTC/keystore/UTC--2019-03-25T09-10-35.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
.address need correct "0xooooooooooooooooooooooooo"
.password need correct, this example is empty.
.web3 localhost is fake, don't need have geth.


var keythereum = require("keythereum");
var datadir = "UTC";
var address= "0xooooooooooooooooooooooooo";
const password = "";

var keyObject = keythereum.importFromFile(address, datadir);
var privateKey = keythereum.recover(password, keyObject);
console.log(privateKey.toString('hex'));

Web3 = require('web3')
web3 = new Web3(new Web3.providers.HttpProvider("localhost"));  
var address = web3.eth.accounts.privateKeyToAccount("0x"+privateKey.toString('hex'));
console.log(address);

[轉]Go面向对象编程以及在Tendermint/Cosmos-SDK中的应用

https://segmentfault.com/a/1190000019776978

Firebase Database Rules

https://www.oxxostudio.tw/articles/201904/firebase-realtime-database-rules.html

https://angularfirebase.com/lessons/understanding-firebase-database-rules-by-example/

ethereum Solidity v0.5.0 Breaking Changes

https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html#example
https://github.com/ethereum/solidity/blob/develop/Changelog.md

[轉]以太坊智能合约Solidity 0.5.0版本重大变化

https://zhuanlan.zhihu.com/p/54169418


随着solidity 0.5.0 nightly build版本的稳步推进,正式版也将在不久的将来与开发者见面.作为一个大版本更新,新版引入了很多特性,也废弃了很多关键字,比如

.call()不仅可以获知远程调用执行成功与否,还将获得远程调用执行的返回值
ABI解码做了新的处理规范,有效防御了"短地址攻击"
address地址类型细分成 address和 address payable
uintY和 bytesX不能直接转换
回退函数必须显式声明为 external可见性
构造函数必须用 constructor关键字定义
用于抛出异常的 throw关键字弃用, 函数状态可变性修饰符必须用 view,不能混用 constant和 view
...
下面我们将对这些改变一一予以介绍,最后给出一个示例代码,对比展示新旧版solidity代码写法的区别,供大家参考.

显式声明
函数可见性
函数可见性必须显式声明. 之前, 函数如果不显式声明,将默认 public可见性.
public: constructor构造函数必须声明为 public可见性,否则编译报错.
external: 回退函数(fallback function), 接口(interface)的函数必须声明为 external可见性,否则编译报错.
存储位置
结构体(struct),数组(array),映射(mapping)类型的变量必须显式声明存储位置( storage, memeory, calldata),包括函数参数和返回值变量都必须显式声明.
external 的函数参数需显式声明为 calldata.
合约与地址
contract合约类型不再包括 address类型的成员函数,必须显式转换成 address地址类型才能使用 send(), transfer(), balance等与之相关的成员函数/变量成员.
address地址类型细分为 address和 address payable,只有 address payable可以使用 transfer(), send()函数.
address payable类型可以直接转换为 address类型, 反之不能.
但是 address x可以通过 address(uint160(x)),强制转换成 address payable类型.
如果 contract A不具有 payable的回退函数, 那么 address(A)是 address类型.
如果 contract A具有 payable的回退函数, 那么 address(A)是 address payable类型.
msg.sender属于 address payable类型.
转换与填充(padding)
uintY与 bytesX
因为填充(padding)的时候, bytesX是右填充(低比特位补0),而 uintY是左填充(高比特位补0),二者直接转换可能会导致不符合预期的结果,所以现在当 bytesX和 uintY长度大小不一致(即X*8 != Y)时,不能直接转换,必须先转换到相同长度,再转换到相同类型.
10进制数值不能直接转换成 bytesX类型, 必须先转换到与 bytesX相同长度的 uintY,再转换到 bytesX类型
16进制数值如果长度与 bytesX不相等,也不能直接转换成 byteX类型
ABI
字面值必须显式转换成类型才能使用 abi.encodePacked()
ABI编码器在构造外部函数入参和 abi.encode()会恰当地处理 bytes和 string类型的填充(padding),若不需要进行填充,请使用 abi.encodePacked()
ABI解码器在解析函数入参和 abi.decode()时,如果发现 calldata太短或超长,将直接抛出异常,而不是像之前自动填充(补0)和截断处理,从而有效地遏制了短地址攻击.
.call()族函数( .call(), .delegatecall(), .staticcall())和 哈希函数( keccak256(), sha256(), ripemd160())只接受一个参数 bytes,且不进行填充(padding)处理.
.call()空参数必须写成 .call("")
.call(sig,a,b,c)必须写成 .call(abi.encodeWithSignature(sig,a,b,c)),其他类推
keccak256(a,b,c)必须写成 keccak256(abi.encodePacked(a,b,c)),其他类推
另外, .call()族函数之前只返回函数执行成功是否的 bool, 现在还返回函数执行的返回值,即 (bool,bytes memory). 所以之前 boolresult=.call(sig,a,b,c)现在必须写成 (boolresult,bytes memory data)=.call(sig,a,b,c).
不允许的写法
在之前版本的solidity编译,以下不允许的写法只会导致 warnings报警,现在将直接 errors报错.

不允许声明0长度的定长数组类型.
不允许声明0结构体成员的结构体类型.
不允许声明未初始化的 storage变量.
不允许定义具有命名返回值的函数类型.
不允许定义非编译期常量的 constant常量. 如 uintconstant time=now;是不允许的.
不允许 0X(X大写)做16进制前缀,只能用 0x.
不允许16进制数和单位名称组合使用. 如 value=0xffether必须写成 value=0xff*1ether.
不允许小数点后不跟数字的数值写法. 如 value=255.0ether不能写成 value=255.ether.
不允许使用一元运算符 +. 例如 value=1ether不能写成 value=+1ether.
不允许布尔表达式使用算术运算.
不允许具有一个或多个返回值的函数使用空返回语句.
不允许未实现的函数使用修饰符(modifier).
不允许 msg.value用在非 payable函数里以及此函数的修饰符(modifier)里.
废弃的关键字/函数
years时间单位已弃用,因为闰年计算容易导致各种问题.
var已弃用,请用 uintY精确声明变量长度.
constant函数修饰符已弃用,不能用作修饰函数状态可变性, 请使用 view关键字.
throw关键字已弃用,请使用 revert(), require(), assert()抛出异常.
.callcode()已弃用,请使用 .delegatecall(). 但是注意,在内联汇编仍可使用.
suicide()已弃用, 请使用 selfdestruct().
sha3()已弃用,请使用 keccak256().
构造函数
构造函数必须用 constructor关键字定义. 之前,并未强制要求,既可以用合约同名函数定义构造函数,也可以用 constructor关键字定义.
不允许调用没有括号的基类构造函数.
不允许在同一继承层次结构中多次指定基类构造函数参数.
不允许调用带参数但具有错误参数计数的构造函数.如果只想在不提供参数的情况下指定继承关系,请不要提供括号.
其他
do...while循环里的 continue不再跳转到循环体内,而是跳转到 while处判断循环条件,若条件为假,就退出循环.这一修改更符合一般编程语言的设计风格.
实现了C99风格的作用域:
变量必须先声明,后使用.之前,是可以先使用,后声明,现在会导致编译报错.
只能在相同或嵌套作用域使用.比如 if(){...}, do{...}while();, for{...}块内声明的变量,不能用在块外.
变量和结构体的循环依赖递归限制在256层.
pure和 view函数在EVM内部采用 staticcall操作码实现(EVM版本>=拜占庭),而非之前的 call操作码,这使得状态不可更改(state changes disallowed)在虚拟机层面得到保证


示例



以下示例显示了Solidity v0.5.0的合约及其更新版本,其中包含本节中列出的一些更改。

旧版:


// 这个不能编译
pragma solidity ^0.4.25;
contract OtherContract {
   uint x;
   function f(uint y) external {
      x = y;
   }
   function() payable external {}
}

contract Old {
   OtherContract other;
   uint myNumber;

   //没有提供函数可变性,不是错误。
   function someInteger() internal returns (uint) { return 2; }

//未提供功能可见性,不是错误。
  //没有提供函数可变性,不是错误。
   function f(uint x) returns (bytes) {
      // Var 可以用
      var z = someInteger();
      x += z;
      // Throw 可以用
      if (x > 100)
         throw;
      bytes b = new bytes(x);
      y = -3 >> 1;
      // y =-2
      do {
         x += 1;
         if (x > 10) continue;
         //'继续'会导致无限循环。
      } while (x < 11);
      // 返回bool
      bool success = address(other).call("f");
      if (!success)
         revert();
      else {
         //可以在使用后声明局部变量。
         int y;
      }
      return b;
   }

   //不需要'arr'的显式数据位置
   function g(uint[] arr, bytes8 x, OtherContract otherContract) public {
      otherContract.transfer(1 ether);

//由于uint32(4字节)小于bytes8(8字节),
   //  x的前4个字节将丢失。 这可能会导致
   // 由于bytesX是右填充的意外行为。      
uint32 y = uint32(x);
      myNumber += y + msg.value;
   }
}

新版本:

pragma solidity >0.4.99 <0.6.0;
contract OtherContract {
   uint x;
   function f(uint y) external {
      x = y;
   }
   function() payable external {}
}

contract New {
   OtherContract other;
   uint myNumber;

   //必须指定函数可变性。
   function someInteger() internal pure returns (uint) { return 2; }

  //必须指定功能可见性。
     //必须指定函数可变性。
   function f(uint x) public returns (bytes memory) {
      //现在必须明确给出类型。
      uint z = someInteger();
      x += z;
      // Throw 不允许
      require(x > 100);
      int y = -3 >> 1;
      // y == -2 (正确)
      do {
         x += 1;
         if (x > 10) continue;
         //'继续'跳到下面的条件。
      } while (x < 11);
//调用返回(bool,bytes)。
      // 必须指定数据位置。
      (bool success, bytes memory data) = address(other).call("f");
      if (!success)
         revert();
      return data;
   }

   using address_make_payable for address;
   //必须指定'arr'的数据位置
   function g(uint[] memory arr, bytes8 x, OtherContract otherContract, address unknownContract)
 public payable {
      // 未提供“otherContract.transfer”。
      //由于'OtherContract'的代码是已知的并具有后备
      // function,address(otherContract)的类型为“地址应付”。
      address(otherContract).transfer(1 ether);
    //未提供'unknownContract.transfer'。
//未提供'address(unknownContract).transfer'
//因为'地址(unknownContract)'不是'地址应付'。
//如果该函数采用您要发送的“地址”
//资金到,您可以通过'uint160'将其转换为'地址应付'。
//注意:不建议使用此类型和显式类型
//应尽可能使用“应付地址”。
//为了提高清晰度,我们建议使用库
//转换(在本例中的合同之后提供)。
      address payable addr = unknownContract.make_payable();
      require(addr.send(1 ether));
//由于uint32(4字节)小于bytes8(8字节),
//不允许转换。
//我们需要先转换为通用尺寸:
      bytes4 x4 = bytes4(x); //填充发生在右侧
      uint32 y = uint32(x4); //转换是一致的
//'msg.value'不能用于'非应付'功能。
//我们需要支付功能
      myNumber += y + msg.value;
   }
}
//我们可以定义一个库来显式转换``address``
//将``地址应付款``作为一种解决方法。
library address_make_payable {
   function make_payable(address x) internal pure returns (address payable) {
      return address(uint160(x));
   }
}

Material Design Lite google

https://github.com/google/material-design-lite

希望香港不要踩底線啊~~

中共的底線港獨是不能碰,打砸搶也不行,平和抗議示威肯定可以,希望香港不要踩底線啊~~

https://www.youtube.com/watch?v=HAP3QCgD6YA 郭文貴資助梁頌恆搞港獨(美國) -- 錢、簽證、政治保護都準備好了

https://youtu.be/-FuVqqPCy98?list=FLGJ0IWhI8tRS57Y4rmEu1HA&t=695 六四 美國 -- 護照

https://www.youtube.com/watch?v=Y3AUKmNorPQ&list=FLGJ0IWhI8tRS57Y4rmEu1HA&index=26&t=0s 寒梅的六四
(這人影片有爭議,但主要看當初留下來的影片和一些資料)

https://youtu.be/SE6g2DVqr_4?list=PLBAD92DFCE1748197&t=235 西藏 美國 CIA介入 提供武器判亂 獨立

https://youtu.be/EM_48sSLS7o?t=303 西藏 嘉樂頓珠 達懶二哥回憶錄 接觸CIA,給支持
與美國中情局的合作,是我一生都懊悔的事情

https://youtu.be/O0fhyJxUcW0?list=FLGJ0IWhI8tRS57Y4rmEu1HA&t=355 香港遠東情報中心 斯諾登 菱鏡計畫


https://zh.wikipedia.org/wiki/%E7%A8%9C%E9%8F%A1%E8%A8%88%E7%95%AB 菱鏡計畫 2007年 美國絕密級網絡監控計劃
https://youtu.be/BrruzdYuZiA?t=55 法國報紙內容
https://www.storm.mg/article/31057 台灣竟也不可免地陷入此一偵監網羅

https://zh.wikipedia.org/wiki/%E9%9C%87%E7%BD%91 震網(Stuxnet) 目標為伊朗使用西門子控制系統的高價值基礎設施
美國官員承認這個病毒是由美國國家安全域在以色列協助下研發,以奧林匹克網路攻擊行動為計劃代號,目的在於阻止伊朗發展核武

【竹老板】大陸人可以批評自己的國家和官員嘛?//批評官員等於愛國嘛?
https://youtu.be/W29_U-Ev8MI?t=177

【竹老板】扯闲篇:墙倒了谁倒霉
https://youtu.be/1Z70CwAiuDc?t=72

https://youtu.be/FiyJf-8lMmo?t=193 德國知事從愛台灣 到 和平統一無望
https://youtu.be/FiyJf-8lMmo?t=980 台灣情 沒防火牆後 的 厭惡

etherniti swagger

https://www.etherniti.org/blog/development/swagger/

http://dev.proxy.etherniti.org/swagger/

[轉]nodejs vs golang Web3 Performance comparison

https://docs.etherniti.org/architecture/benchmarks/performance_test/

golang ethereum address regexp check

https://docs.etherniti.org/architecture/optimizations/address-validation/


package main

import (
    "fmt"
    "regexp"
)

var (
    re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
)

func IsValidAddress(v string) bool {
    return re.MatchString(v)
}

func main() {
    fmt.Println(IsValidAddress("0x323b5d4c32345ced77393b3530b1eed0f346429d")) // true
    fmt.Println(IsValidAddress("0xXYZb5d4c32345ced77393b3530b1eed0f346429d")) // false
}

[轉]Node 在正式環境運行的對應方式

https://adon988.logdown.com/posts/7831077-the-corresponding-way-of-node-operation-in-the-formal-environment

在這裡要探討關於 node 到底適不適合在正式環境運行,在一開場首先說明我"過去"對於這個問題的看法,答案是:不適合。

基本面

https://www.facebook.com/groups/452453028629725/permalink/499354767272884/

#股票
#鴻海
#基本面
#a大

我知道對大部份的人來說基本了點,但不少的新手進來,我認為很基本的東西,大家都會,也許真的有人不會,所以會的人就忍耐一下,當做是複習。

如何研究一檔股票的基本價值

1、 股本及股東權益

參考網址 https://goodinfo.tw/StockInfo/StockFinDetail.asp?RPT_CAT=BS_M_QUAR&STOCK_ID=2317

一般來說,我在看一檔股票時,我會按照下面的順序看最基本的公司資料,以目前我的資金我會傾向選擇大型權值股,最好這檔公司是偏穩健型,股價因某一些原因又被低估,所以一開始我會先看公司的股本及股東權益,因為如果股本太小公司很容易被某一些主力就控制住了,股價波動劇烈,流動性相對不好,我也會看股東權益,看公司的保留盈餘有多少,公司是不是有足夠的錢,因為是基本的價值,所以還不去考慮庫存,現金,應收帳款,應付帳款,客戶,土地廠房,設備…等,因為一開始是選股,還不需要看這麼細,如果一開始的五點不滿足,基本上是不需要再往更深去看。


2、 看公司歷年的股息
參考網址 https://goodinfo.tw/StockInfo/StockDividendPolicy.asp?STOCK_ID=2317

看完股本及股東權益後,這時要先想好退路,股息是保命符,所以我放在第二項,我評估我要花多久時間去化解風險,每年我可以領到多少殖利率,最差的情況我該抱幾年。


3、 看公司的毛利率、營利率,稅後盈餘、淨值
參考網址 https://goodinfo.tw/StockInfo/StockFinDetail.asp?RPT_CAT=XX_M_QUAR_ACC&STOCK_ID=2317

歷年股息看完後,接下來是看公司基本的經營能力,毛利率,營利率,稅後盈餘及淨值,稍微看一下這歷年的經營趨勢,看一下公司淨值有多少,每年可以賺多少,這一點可以簡單的評估出公司之前的競爭力如何,因為目前是基本評估階段,當基本的符合後,才會更深的看公司產業面,組織架構,競爭力,看公司未來還能賺幾年,這幾年獲利會不會減少。


4、 看公司歷年的股價
參考網址 https://goodinfo.tw/StockInfo/ShowK_Chart.asp?STOCK_ID=2317&CHT_CAT2=MONTH

看完歷年公司經營能力後,這時要透過歷年股價去看市場投資人,外資群願意給公司多少的價格,因為你單純看基本面,你看不出該個股中投資人的心態,透過歷年的股價,可以看出獲利對股價的關係。


5、 三大法人持股比例
參考網址 https://goodinfo.tw/StockInfo/ShowBuySaleChart.asp?STOCK_ID=2317&CHT_CAT=YEAR

最後再看一下三大法人歷年持有該公司的比例,看一下三大法人的心態如何,持股的水位如何,是不是有機會增加更高的持股水位或是持有到某一個水準時這檔就偏主力控制股。

我們很多的文章都是看更深入的基本面及產業面,為了確保一般人都懂我在幹嘛,這是最基本一開始我會考慮的事,之前我們都在更深入的看庫存,應收帳款,現金,保留盈餘,公司組織,公司架構,各子公司的獲利情況,業內、業外怎麼賺的…等,我相信很多人能組織起來我分析基本面的內容,為了讓新進的人可以了解,這一篇給你們當初階篇。

郭董 0~6歲

郭董真的選上了,要落實政策,進入公務體系

他在鴻海的幹部能帶到政府內嗎?這些幹部要嗎?
單論人 薪水天差地別,加薪 要改法條,要審預算;要人進來,要通過國家考試,不能隨便任用;發包標案找外包團隊(會有資安、密等),圖利
像蔡英文成立各種單位找人進來,會不會有多重架構?會不會有養肥貓?會不會有一堆質疑?對公務體系了解的團隊,單位權高多頭馬車,單位權少拉不動,基權公務員加重工作又不加薪?擴大招人,預算、編制人數、法條規定,立法是否過半?過半後立法是否獨斷?

郭董出錢成立團隊、單位,一毛不花政府的錢,政府也不見得能用......很多問題在裡面
郭董錢進政府,要統籌分配,還是能專款,法源依據?是進中央,還是地方?

他真正手下只有原有的公務體系,他只能任命高階政務官,真正執行的還是事務官,那他手上有什麼政務官懂真正事務體系?
像柯P,達不到要求一直砍人換人,政策真的能落實? (最近聽演講-燈會團隊說和公務體系交手成功案例,夠敢還是有一定改變和效果,但預算還是被質疑)

預算不夠,會不會像韓國瑜一樣拿第二預備金,先做再說,過程就一直被罵,一直被質疑?當然要能被罵,也要能被質疑 (老人家會不會氣到中風...)
郭董年紀大了,萬一說話不小心說錯或說太快,可能就會像馬英九一樣,被笑到翻,不知鹿

法案民進黨不會杯革?不會佔議事台?發動社運團體、媒體進行洗腦?上街抗議?
要對手支持派王金平來處理,台面下“溝通“,一溝通就會有黃國昌出來,要透明反黑箱


以上是純幻想,郭董選上後必能有另一番做為,打破上述的框框架架

警 買 電擊槍

政府依預算行使,預算已經編的不能挪它用,要申請"特別"預算,要上文,要審,上面也要有錢,需依法行政

在台面上宣告加碼買什麼,還是要照程序走,買要先開標,開標前要有開標文件(除非特殊規格標......),找廠商前要先開規格需求,要開規格需求前要先了解能做到什麼功能、效果,要了解功能、效果要訪問第一線員警,做統計、分析、聽廠商"鬼扯",參考國外等等

等到跑一輪後,到立法院立委們要審,質疑文件太少,是否有效果評估、必要性、達成率,是否要分批執行,必需考量各種方案、更多可能,最少錢做最多的事,要做更多評估,打回或通過

通過後,採買裝備分發,非制式還要分批受訓,受了訓還要確定實際執行面,裝備可靠度,是否統計分析如當初所預期,有,加碼,是否有錢,無,整個案子的錢都白費了


原本有的工作都要做,要再加碼工作量,員警因公務退休金被砍,不離職就不換新血,整個行政越走越慢

公務體系 最終為了加速汰換還是會走回以前的老路,加碼請老的退休,不然新的進不來,加碼的錢又來自稅金,花了一堆社會成本的改革,最終還是稅金要加碼請老的退休

geth poa ethereum 出塊 時間間隔

創世區塊 g

30 seconds




"period": 30,


why-ethereum-transfers-are-so-slow-how-fix

https://born2invest.com/articles/why-ethereum-transfers-are-so-slow-how-fix/

Slow and steady
Ethereum only processes 10 to 15 transactions per second, in large part because all nodes are required to help process all transactions made through the database. By comparison, a credit card company like Visa can process around 45,000 transactions per second.

hyperledger Ansible

https://ibmcode-staging.us-east.containers.mybluemix.net/announcements/provision-hyperledger-fabric-on-multiple-vms-using-ansible/

https://github.com/hyperledger-labs/fabric-vms-provision


https://github.com/hyperledger/cello/tree/master/src/agent/ansible
https://cello.readthedocs.io/en/latest/tutorial/

[轉]三年行业经验总结:我庆幸我在推动联盟链

https://www.infoq.cn/article/J_4LxXrFL0H2djEUCuFK

hypderledger composer

https://hyperledger.github.io/composer/

https://www.mchampaneri.in/2018/03/setup-development-environment-for.html

https://www.codementor.io/hajsf/install-hyperledger-fabric-at-win-10-tb85r9dqg


https://medium.com/beyondi/setup-and-build-hyperledger-fabric-blockchain-applications-b7c476f9cef2


https://mindf.org/setting-up-ubuntu-18-04-on-virtualbox-for-hyperledger-fabric/

??? 台灣觀眾如何被媒體出賣?「媒體洗腦」完全破解!紅色滲透是啥?【記者真心話】Vol.2|懶人包

https://www.youtube.com/watch?v=mVEItYOsXjM&feature=youtu.be&fbclid=IwAR0u5kh2T7HtQdmXZO-d72IoZAfrZZ3-BJnFMDdKTjvgvIYmoGOZBLM1Aj0

1、拿出大陸和早期的新聞來做說明,請問之前蔡總統的狗上新聞,各媒體都有報導,過了二十、三十年後,有人把這些剪在一起,也報導出來,告訴大家蔡總統是一個重視狗,不重視人民,這媒體是不是有問題?在客觀表達上就有問題了
而且還扣上每一間媒體都要聽話?!單單看到這就已經代表公視在沉淪了!一個有客觀公正的人看到這段馬上就要會質疑,它怎麼扣上每一個媒體!另外拿一些國家大事來論就更可笑,試例台灣買美國武器,全台灣媒體都有報導,所以全部的媒體都是官媒囉?這種例子100%肯定邏輯是不通的,為什麼不通?因為內容不見得支持啊!正反的意見從各自媒體支持方向不同而改變內容,這才是公平。
其實這種Youtube我是真的不想看,看了第一段隨便思考一下就能發現一堆問題…
正確報導這種話題本來就不容易,更應該收集齊全資料做展示,剪接也要注意避免產生不公平情況,80%主流意見,20%非主流意見,在同一個時間內報導,是否會造成好像是50% 50%的情況
試思考一下,現在誰不支持蔣中正,我敢說 拿到現今社會,年輕人都支持蔣中正力抗 “中國共產黨“,真正發展軍備跟“中國共產黨“打一仗:多想想這種很奇怪的思想轉換,多想想這個試問吧
請問像youtube這種報導越多,拿著公正當口號,細節到處都是不公正,看越多又不思考,越被洗惱

2、拿財團來當例子… 上面說政府要退出媒體,這裡討論財團買媒體,假設財團不買媒體,媒體怎麼生存,誰要買?嗯,有人提到那就定下法律媒體必OOXX來保障,這有腦嗎?多想想這件事,就會發現這又是一個很可笑的答案
a. TVBS炒HTC
b. 三立炒牧場
請問別家媒體會跟TVBS、三立一起炒嗎?這又扯到另一個買報導問題
一個獨立思考,有公正能力判斷的人,看媒體只看一家,一直看一家報導??!!只看自己喜歡看的?那他怎麼會認為自己是有公正能力判斷的人?假如他看了多家媒體,自然怎麼會被洗腦??!!是自己願意被洗還是怪別人來洗?
這些非常簡單,思考一下,就能得到論述及答案,這支影片怎麼都沒提到,看到這裡,這支影片和它的標題已經漸行漸遠了

3、直接點明旺旺,齊下有很多媒體,播一段董事長的話,我聽了覺得一點問題都沒有,做大陸的生意,當然會說大陸好話,這是表裡如一啊!難道有人期望賺大陸的錢,還要罵大陸,要成為表裡不一的人!要我們整個社會文化成為表裡不一的人?!!
回到2. 你可以看很多媒體啊!
每個人都可以支持統一,支持台獨,有錢的人寫書、辨報、經營媒體、做youtube影片、直播等等,越多人可以表達出來,公正客觀的人就能從中接收到不同的訊息,其中思考

4、拿佔中來論,回到1吧,1在說所有媒體都在報導同一件事,是官媒! 哈,思考一下,這支影不就正在做 “把媒體綁架“,拿 來綁架嗎
旺旺覺得佔中不支持,改報導其他覺得更重要的事,那是它的自由啊!而其他一堆報紙要報導,那也是它的自由啊!
另外再用邏輯思考一下,同樣的“佔中“是誰在洗腦?!所有的媒體都在報導“佔中“,是除了旺旺外,沒在洗你我的腦。
再請問一下,旺旺只佔了一部份媒體吧,那他又怎麼洗腦? 試想 我說某集團洗腦,結果這集團還只佔全部的20%…… 我都無言了
這影片....................真正思考的人都知道他在幹什麼事,拿口號、流行來做 。

5、誰說沒了這些媒體就黑暗了…… 鬼扯什麼 人跟人面對面交流更重,流言就沒有了嗎?

6、誰說台灣媒體只有報導中國的好處?自由獨派死光了,誰說台灣媒體只有報導中國的壞處?統一派死光了!早就有兩派人馬互鬥,這影片用很感性的話:沒有… 照不到…
早就有了啦!在鬼扯什麼啊!另外拿國外媒體也請同樣拿出國外媒體支持中共的報導…看到這裡我在想
做這影片的人,心中早有定見,看到一邊,在說一邊的不足,卻故意忽略明明早就有另一邊的報導
穆斯林照不到,爭眼說瞎話!照不到會“一堆國外媒體爭相報導“ ,影片作者你會知道??!! 你到底在說什麼鬼話啊!

7、請問失去照不到,綠營一堆都在討論,在告訴民眾,影片作者到底你在爭眼說瞎話,說什麼鬼?!三立、自由被現在政府打壓,負責人被國安法送辨,秘密審判、刑求,家人被查水表,沒工作,小孩在校被打被罵?!
還是NCC要求三立、自由不準報導,撤照??!!
當你用感性的語氣說這種話時,你是在用什麼說服,用公正客觀的媒體權,還是自我的意識

整個影片真慘……啊!只有強調不要被中共洗腦,而不是談怎麼避免媒體洗腦
沒有提到提到任何 “要思考“ “要多看“,也沒有提到 “去掉情緒用語“


當用公視的名義時,心中的正義到那去了



https://youtu.be/3lJzka7IKDE?t=1147 小董真心話裡面提到的頂新,最近觀察新聞真的是這樣啊!!!


capacitor barcode scan

If you npm install a Cordova/Capacitor plugin after npx cap add android then make sure you run npx cap update before running from Android Studio again.
If you make html, js, ts, css changes, run ionic build again and also run npx cap copy.
Or when in doubt, run npx cap sync as it does update+copy.

https://github.com/ionic-team/capacitor/issues/1213
https://stackoverflow.com/questions/23060038/cant-use-barcode-scanner-in-cordova-plugin-is-installed

1. init

npx @capacitor/cli create testbarcode
npx cap add android
npx cap sync
npx cap copy
npx cap open android

ctrl+c exit



2. npm i phonegap-plugin-barcodescanner


npm i phonegap-plugin-barcodescanner --save
npx cap sync
npx cap copy

3. modify www/index.html

ADD

<button onclick="myFunction2()">Try it barcode</button>

<script>
    async function myFunction2() {
      cordova.plugins.barcodeScanner.scan(
        result => console.log(result),
        err => console.error(err),
        {
          showTorchButton: true,
          prompt: "Scan your code",
          formats: "QR_CODE",
          resultDisplayDuration: 0
        }
      );
    }
</script>


npx cap sync
npx cap copy

android studio run

PS: use cordova.plugins NOT window.cordova.plugins

siege

http://xstarcd.github.io/wiki/shell/siege.html

https://coder.tw/?p=7198


==========

很像REST Client
1. var = 兩邊不能有空白
EX:
@9020_login = http://192.168.99.100:9020/login

9020_login=http://192.168.99.100:9020/login

2. 當有空白行時
EX:
@_csrf1 = Gxa6Hip4-J_A3L2kpRc72Iclw_Ql8eIcQiTc

@login_challenge = 394bab045e2e4a25be83fe207440787e


如果login_chanllenge是最後一個參數,要補上&
_csrf1=Gxa6Hip4-J_A3L2kpRc72Iclw_Ql8eIcQiTc

login_challenge=394bab045e2e4a25be83fe207440787e&

siege會把CR當成參數內容傳送

==========

siege --help

SIEGE 3.0.6
Usage: siege [options]
siege [options] URL
siege -g URL
Options:
-V, --version VERSION, prints the version number.
-h, --help HELP, prints this section.
-C, --config CONFIGURATION, show the current config.
#在屏幕上打印显示出当前的配置,配置是包括在他的配置文件$HOME/.siegerc中,
#可以编辑里面的参数,这样每次siege 都会按照它运行.
-v, --verbose VERBOSE, prints notification to screen.
#运行时能看到详细的运行信息
-q, --quiet QUIET turns verbose off and suppresses output.
-g, --get GET, pull down HTTP headers and display the
transaction. Great for application debugging.
-c, --concurrent=NUM CONCURRENT users, default is 10
#模拟有n个用户在同时访问,n不要设得太大,因为越大,siege 消耗本地机器的资源越多
-i, --internet INTERNET user simulation, hits URLs randomly.
#随机访问urls.txt中的url列表项,以此模拟真实的访问情况(随机性)
-b, --benchmark BENCHMARK: no delays between requests.
-t, --time=NUMm TIMED testing where "m" is modifier S, M, or H
ex: --time=1H, one hour test.
#持续运行siege ‘n’秒(如10S),分钟(10M),小时(10H)
-r, --reps=NUM REPS, number of times to run the test.
#重复运行测试n次,不能与 -t同时存在
-f, --file=FILE FILE, select a specific URLS FILE.
#指定用urls文件,默认为siege安装目录下的etc/urls.txt
#urls.txt文件:是很多行待测试URL的列表以换行符断开,格式为:
#[protocol://]host.domain.com[:port][path/to/file]
-R, --rc=FILE RC, specify an siegerc file
#指定用特定的siege配置文件来运行,默认的为$HOME/.siegerc
-l, --log[=FILE] LOG to FILE. If FILE is not specified, the
default is used: PREFIX/var/siege.log
#运行结束,将统计数据保存到日志文件siege.log中,可在.siegerc中自定义日志文件
-m, --mark="text" MARK, mark the log file with a string.
-d, --delay=NUM Time DELAY, random delay before each requst
between 1 and NUM. (NOT COUNTED IN STATS)
#hit每个url之间的延迟,在0-n之间
-H, --header="text" Add a header to request (can be many)
-A, --user-agent="text" Sets User-Agent in request
-T, --content-type="text" Sets Content-Type in request




** SIEGE 2.72
** Preparing 300 concurrent users for battle.
The server is now under siege.. done.

Transactions: 30000 hits #完成30000次处理
Availability: 100.00 % #成功率
Elapsed time: 68.59 secs #总共使用时间
Data transferred: 817.76 MB #共数据传输 817.76 MB
Response time: 0.04 secs #响应时间,显示网络连接的速度
Transaction rate: 437.38 trans/sec #平均每秒完成 437.38 次处理
Throughput: 11.92 MB/sec #平均每秒传送数据
Concurrency: 17.53 #实际最高并发连接数
Successful transactions: 30000 #成功处理次数
Failed transactions: 0 #失败处理次数
Longest transaction: 3.12 #每次传输所花最长时间
Shortest transaction: 0.00 #每次传输所花最短时间

nightwatch OpenID Hydra Windows

Windows

Update chrome v75



> mkdir t
> cd t
> midir tests

> npm install nightwatch  --save-dev
> npm install chromedriver --save-dev

> nano nightwatch.js
require('nightwatch/bin/runner.js');

> nano nightwatch.conf.js
const chrome = require('chromedriver')

module.exports = {
  src_folders: ['tests'],
  webdriver: {
    start_process: true,
    server_path: chrome.path,
    port: 9515,
  },
  test_settings: {
    default: {
      desiredCapabilities: {
        browserName: 'chrome',
      },
    },
  },
}

> nano tests/test.js
module.exports = {
  'step one: navigate to google' : function (browser) {
    for (var i = 0; i < 10; i += 1) {
      browser
        .url('https://t.tt:9010')
        .waitForElementVisible('body', 1000)
        .click('a')
        .waitForElementVisible('input[type=email]')
        .setValue('input[type=email]', 'foo@bar.com')
        .setValue('input[type=password]', 'foobar')
        .click('input[type=submit]', function(result) {
          this.assert.strictEqual(result.status, 0);
        })
        .waitForElementVisible('input[type=checkbox]')
        .click('input[id=openid]')
        .click('input[id=offline]')
        .click('input[id=accept]', function(result) {
          this.assert.strictEqual(result.status, 0);
        })
    }
  },
};

> node nightwatch.js tests/test.js

OpenID Hydra session data can't show at userinfo or introspect

If you use consent website(official login&consent) run all step, routes/consent.js session part need remove mark, surely you can get session data.





@token= xLPcJ3tobDqGUDxIVTxWt2p7w_odZSV22IAlUf5QPZU.YD6R_xKQ2ldCLbEV7mmc01E6ZLzemzdEC5H4-otTMPg

### userinfo
GET https://openid.hydra:9001/userinfo
Authorization: Bearer {{token}}

### introspect
POST https://openid.hydra:9002/oauth2/introspect
Content-Type: application/x-www-form-urlencoded

token={{token}}
&scope=openid+photos.read

PS:&scope=openid+photos.read can remove.

But you use REST Client need fix. Put session data by yourself.



### accept conent scope
PUT https://192.168.99.100:9002/oauth2/auth/requests/consent/accept?consent_challenge={{consent_challenge}}
Content-Type: application/json

{
  "grant_scope": ["openid", "photos.read"],
  "session": {
    "access_token": { "foo": "bar" },
    "id_token": { "baz": "bar" }
  }
}

Try and watch many document. Can't get real why. Official Website no any discuss.



OpenID hydra

https://www.ory.sh/docs/next/hydra/oauth2#oauth-20-scope

A OAuth 2.0 Scope is not a permission:

A permission allows an actor to perform a certain action in a system: Bob is allowed to delete his own photos.
OAuth 2.0 Scope implies that an end-user granted certain privileges to a client: Bob allowed the OAuth 2.0 Client to delete all users.
The OAuth 2.0 Scope can be granted without the end-user actually having the right permissions. In the examples above, Bob granted an OAuth 2.0 Client the permission ("scope") to delete all users in his name. However, since Bob is not an administrator, that permission ("access control") is not actually granted to Bob. Therefore any request by the OAuth 2.0 Client that tries to delete users on behalf of Bob should fail.


我授權程式可以“讀取、刪除“權限,但實際上授權程式能不能真正“讀取、刪除“資料 或是 真正有“讀取、刪除“權限 是不一定有的

OpenID hydra context data save

hydra login consent node
https://github.com/ory/hydra-login-consent-node

When login success, context data be saved .
Can use
GET https://openid.hydra:9002/oauth2/auth/sessions/consent?subject=foo@bar.com HTTP/1.1
check by subject.

routes/login.js



hydra.acceptLoginRequest(challenge, {

    context: {
      "test1": "test1",
      "test2": { "test2i": "test2i"}
    },

Database keep context

Table name: hydra_oauth2_consent_request save context data. Here is Postgresql (pg).



===== Postgresql command ====

1. Login Postgresql (pg) docker

2.

psql hydra -U hydra

#login pg (already in db cmd)
\dt;
select * from hydra_oauth2_consent_request;


=============== userinfo ===============

GET https://openid.hydra:9001/userinfo
Authorization: Bearer pFmYrUWtkGswx6RjvsGfgUAl4gV88id90P7hVLHUfQ4.AhbkWRawXV35S_V6Nq-Hf3DlBZ8Dl622sB4M3dg_hNQ

{
  "sid": "891db392-859c-49d9-958c-83135f6986ee",
  "sub": "foo@bar.com"
}

sid can check by use sub.

GET https://openid.hydra:9002/oauth2/auth/sessions/consent?subject=foo@bar.com HTTP/1.1

OpenID hydra docker-compose STOP

https://github.com/ory/examples/blob/master/full-stack/docker-compose.yml


Maybe use 5 min quickstart.yml better.

OpenID hydra SSL problem Finish!


1、use docker-machine create vm get ip: 192.168.99.100

2、deploy
https://www.ory.sh/docs/next/hydra/configure-deploy


docker network create hydraguide



docker run \
  --network hydraguide \
  --name ory-hydra-example--postgres \
  -e POSTGRES_USER=hydra \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=hydra \
  -d postgres:9.6



export SECRETS_SYSTEM=this_needs_to_be_the_same_always_and_also_very_$3cuR3-._

export DSN=postgres://hydra:secret@ory-hydra-example--postgres:5432/hydra?sslmode=disable

docker pull oryd/hydra:latest



docker run -it --rm \
  --network hydraguide \
  oryd/hydra:latest \
  migrate sql --yes $DSN

=====creat ssl cert and key====
!!注意!! 產生方式改用 https://sueboy.blogspot.com/2019/08/openssl-self-signed-certificate.html 較為保險,不容易發生 ERR_SSL_VERSION_OR_CIPHER_MISMATCH 錯誤!

create two cert. 1. t.tt 2. openid.hydra



In vm
openssl genrsa -out t.tt.key 2048
openssl ecparam -genkey -name secp384r1 -out t.tt.key
openssl req -new -x509 -sha256 -key t.tt.key -out t.tt.crt -days 3650
Important!! t.tt.crt step: Common Name (e.g. server FQDN or YOUR name) []: t.tt


openssl genrsa -out openid.hydra.key 2048
openssl ecparam -genkey -name secp384r1 -out openid.hydra.key
openssl req -new -x509 -sha256 -key openid.hydra.key -out openid.hydra.crt -days 3650
Important!! openid.hydra.crt step: Common Name (e.g. server FQDN or YOUR name) []: openid.hydra

Use openid.hydra.key and openid.hydra.crt to base64 code
https://www.base64encode.org/

openid.hydra.key

-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDCKnGgVqIW7YinbQeyPGyQ44Gu6UQDzU9HCKb33MifxRXE0dnu6+7Zu
0tBTqHPDuLygBwYFK4EEACKhZANiAARnx56OcxcrEdlbe8MtRuEqXev8DDrhzebF
386R8CdPX4eQb6fYzzAT/uwI0lL7oFiDXC7CBKZfTq7EK3xO3WZZRJ2k0D7NsKwg
TJYzrqOBis0MxkokaTYUrzhJ1pJcyfY=
-----END EC PRIVATE KEY-----


openid.hydra.crt

-----BEGIN CERTIFICATE-----
MIICPTCCAcKgAwIBAgIJAMwF4bT4oJxtMAoGCCqGSM49BAMCMFwxCzAJBgNVBAYT
AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn
aXRzIFB0eSBMdGQxFTATBgNVBAMMDG9wZW5pZC5oeWRyYTAeFw0xOTA2MTcwMTIx
MzdaFw0yOTA2MTQwMTIxMzdaMFwxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l
LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTATBgNV
BAMMDG9wZW5pZC5oeWRyYTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGfHno5zFysR
2Vt7wy1G4Spd6/wMOuHN5sXfzpHwJ09fh5Bvp9jPMBP+7AjSUvugWINcLsIEpl9O
rsQrfE7dZllEnaTQPs2wrCBMljOuo4GKzQzGSiRpNhSvOEnWklzJ9qNQME4wHQYD
VR0OBBYEFG+vzfB1beg3UZtJXEvV9dMkXo6gMB8GA1UdIwQYMBaAFG+vzfB1beg3
UZtJXEvV9dMkXo6gMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDaQAwZgIxALPv
86EHTTTIKpBGvT+ccV7wcH/8HR+slad/YPXKRVpwdCo52eTOWpCKgFjkG4BawQIx
ALlFdX0lI6g8WKyaE5f+2FdI1aejCAmwLOM6SDRa4UGn+Ckep8IcxmBL2/Be3IVz
8g==
-----END CERTIFICATE-----


SERVE_TLS_KEY_BASE64=LS0tLS1CRUdJTiBFQyBQQVJBTUVURVJTLS0tLS0KQmdVcmdRUUFJZz09Ci0tLS0tRU5EIEVDIFBBUkFNRVRFUlMtLS0tLQotLS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUlHa0FnRUJCRENLbkdnVnFJVzdZaW5iUWV5UEd5UTQ0R3U2VVFEelU5SENLYjMzTWlmeFJYRTBkbnU2KzdadQowdEJUcUhQRHVMeWdCd1lGSzRFRUFDS2haQU5pQUFSbng1Nk9jeGNyRWRsYmU4TXRSdUVxWGV2OEREcmh6ZWJGCjM4NlI4Q2RQWDRlUWI2Zll6ekFUL3V3STBsTDdvRmlEWEM3Q0JLWmZUcTdFSzN4TzNXWlpSSjJrMEQ3TnNLd2cKVEpZenJxT0JpczBNeGtva2FUWVVyemhKMXBKY3lmWT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

SERVE_TLS_CERT_BASE64=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNQVENDQWNLZ0F3SUJBZ0lKQU13RjRiVDRvSnh0TUFvR0NDcUdTTTQ5QkFNQ01Gd3hDekFKQmdOVkJBWVQKQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbgphWFJ6SUZCMGVTQk1kR1F4RlRBVEJnTlZCQU1NREc5d1pXNXBaQzVvZVdSeVlUQWVGdzB4T1RBMk1UY3dNVEl4Ck16ZGFGdzB5T1RBMk1UUXdNVEl4TXpkYU1Gd3hDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWwKTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhGVEFUQmdOVgpCQU1NREc5d1pXNXBaQzVvZVdSeVlUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkdmSG5vNXpGeXNSCjJWdDd3eTFHNFNwZDYvd01PdUhONXNYZnpwSHdKMDlmaDVCdnA5alBNQlArN0FqU1V2dWdXSU5jTHNJRXBsOU8KcnNRcmZFN2RabGxFbmFUUVBzMndyQ0JNbGpPdW80R0t6UXpHU2lScE5oU3ZPRW5Xa2x6SjlxTlFNRTR3SFFZRApWUjBPQkJZRUZHK3Z6ZkIxYmVnM1VadEpYRXZWOWRNa1hvNmdNQjhHQTFVZEl3UVlNQmFBRkcrdnpmQjFiZWczClVadEpYRXZWOWRNa1hvNmdNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURhUUF3WmdJeEFMUHYKODZFSFRUVElLcEJHdlQrY2NWN3djSC84SFIrc2xhZC9ZUFhLUlZwd2RDbzUyZVRPV3BDS2dGamtHNEJhd1FJeApBTGxGZFgwbEk2ZzhXS3lhRTVmKzJGZEkxYWVqQ0Ftd0xPTTZTRFJhNFVHbitDa2VwOEljeG1CTDIvQmUzSVZ6CjhnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=


docker run -d \
  --name ory-hydra-example--hydra \
  --network hydraguide \
  -p 9001:4444 \
  -p 9002:4445 \
  -e SECRETS_SYSTEM=$SECRETS_SYSTEM \
  -e DSN=$DSN \
  -e URLS_SELF_ISSUER=https://openid.hydra:9001/ \
  -e URLS_CONSENT=http://192.168.99.100:9020/consent \
  -e URLS_LOGIN=http://192.168.99.100:9020/login \
  -e LOG_LEVEL=debug \
  -e OAUTH2_EXPOSE_INTERNAL_ERRORS=1 \
  -e SERVE_PUBLIC_CORS_ENABLED=true \
  -e SERVE_PUBLIC_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE \
  -e SERVE_ADMIN_CORS_ENABLED=true \
  -e SERVE_ADMIN_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE \
  -e SERVE_TLS_KEY_BASE64=LS0tLS1CRUdJTiBFQyBQQVJBTUVURVJTLS0tLS0KQmdVcmdRUUFJZz09Ci0tLS0tRU5EIEVDIFBBUkFNRVRFUlMtLS0tLQotLS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUlHa0FnRUJCRENLbkdnVnFJVzdZaW5iUWV5UEd5UTQ0R3U2VVFEelU5SENLYjMzTWlmeFJYRTBkbnU2KzdadQowdEJUcUhQRHVMeWdCd1lGSzRFRUFDS2haQU5pQUFSbng1Nk9jeGNyRWRsYmU4TXRSdUVxWGV2OEREcmh6ZWJGCjM4NlI4Q2RQWDRlUWI2Zll6ekFUL3V3STBsTDdvRmlEWEM3Q0JLWmZUcTdFSzN4TzNXWlpSSjJrMEQ3TnNLd2cKVEpZenJxT0JpczBNeGtva2FUWVVyemhKMXBKY3lmWT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= \
  -e SERVE_TLS_CERT_BASE64=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNQVENDQWNLZ0F3SUJBZ0lKQU13RjRiVDRvSnh0TUFvR0NDcUdTTTQ5QkFNQ01Gd3hDekFKQmdOVkJBWVQKQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbgphWFJ6SUZCMGVTQk1kR1F4RlRBVEJnTlZCQU1NREc5d1pXNXBaQzVvZVdSeVlUQWVGdzB4T1RBMk1UY3dNVEl4Ck16ZGFGdzB5T1RBMk1UUXdNVEl4TXpkYU1Gd3hDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWwKTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhGVEFUQmdOVgpCQU1NREc5d1pXNXBaQzVvZVdSeVlUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkdmSG5vNXpGeXNSCjJWdDd3eTFHNFNwZDYvd01PdUhONXNYZnpwSHdKMDlmaDVCdnA5alBNQlArN0FqU1V2dWdXSU5jTHNJRXBsOU8KcnNRcmZFN2RabGxFbmFUUVBzMndyQ0JNbGpPdW80R0t6UXpHU2lScE5oU3ZPRW5Xa2x6SjlxTlFNRTR3SFFZRApWUjBPQkJZRUZHK3Z6ZkIxYmVnM1VadEpYRXZWOWRNa1hvNmdNQjhHQTFVZEl3UVlNQmFBRkcrdnpmQjFiZWczClVadEpYRXZWOWRNa1hvNmdNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURhUUF3WmdJeEFMUHYKODZFSFRUVElLcEJHdlQrY2NWN3djSC84SFIrc2xhZC9ZUFhLUlZwd2RDbzUyZVRPV3BDS2dGamtHNEJhd1FJeApBTGxGZFgwbEk2ZzhXS3lhRTVmKzJGZEkxYWVqQ0Ftd0xPTTZTRFJhNFVHbitDa2VwOEljeG1CTDIvQmUzSVZ6CjhnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= \
  oryd/hydra:latest serve all
LOG_LEVEL ~ SERVE_ADMIN_CORS_ALLOWED_METHODS not important, add by yourself.



docker run -d \
  --name ory-hydra-example--consent \
  -p 9020:3000 \
  --network hydraguide \
  -e HYDRA_ADMIN_URL=https://ory-hydra-example--hydra:4445 \
  -e NODE_TLS_REJECT_UNAUTHORIZED=0 \
  oryd/hydra-login-consent-node:latest



docker run --rm -it \
  -e HYDRA_ADMIN_URL=https://ory-hydra-example--hydra:4445 \
  --network hydraguide \
  oryd/hydra:latest \
  clients create --skip-tls-verify \
    --id auth-code-client \
    --secret secret \
    --grant-types authorization_code,refresh_token \
    --response-types token,code,id_token \
    --scope openid,offline,photos.read \
    --callbacks https://t.tt:9010/callback
This step is different quickstart.yml. Use https and t.tt domain. quickstart.yml start serve --dangerous-force-http
All become http. So last step can callback use http. This production way only use https. And token user only http. So use self OpenID client.


1. nano /etc/hosts or windows hosts

127.0.0.1 t.tt

192.168.99.100 openid.hydra


2. use golang OpenID client + ssl

https://blog.csdn.net/wangshubo1989/article/details/77980316
https://github.com/denji/golang-tls


copy t.tt.key and t.tt.crt to go project



main.go


package main

import (
 "context"
 "crypto/tls"
 "fmt"
 "log"
 "net/http"
 "strings"

 "golang.org/x/oauth2"
)

const htmlIndex = `
<html><body>
<a href="/HydraLogin">Log in with Hydra</a>
</body></html>
`
var endpotin = oauth2.Endpoint{
 AuthURL:  "https://openid.hydra:9001/oauth2/auth",
 TokenURL: "https://openid.hydra:9001/oauth2/token",
}

var HydraOauthConfig = &oauth2.Config{
 ClientID:     "auth-code-client",
 ClientSecret: "secret",
 RedirectURL:  "https://t.tt:9010/callback",
 Scopes:       []string{"openid", "offline", "photos.read"},
 Endpoint:     endpotin,
}

const oauthStateString = "gczxkznmjkrksgytsemvwgkf"

func main() {
 http.HandleFunc("/", handleMain)
 http.HandleFunc("/HydraLogin", handleHydraLogin)
 http.HandleFunc("/callback", handleCallback)
 //fmt.Println(http.ListenAndServe(":9010", nil))
 err := http.ListenAndServeTLS(":9010", "t.tt.crt", "t.tt.key", nil)
 if err != nil {
  log.Fatal("ListenAndServe: ", err)
 }
}

func handleMain(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, htmlIndex)
}

func handleHydraLogin(w http.ResponseWriter, r *http.Request) {
 url := HydraOauthConfig.AuthCodeURL(oauthStateString)
 log.Println(url)
 http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func handleCallback(w http.ResponseWriter, r *http.Request) {
 // add transport for self-signed certificate to context
 tr := &http.Transport{
  TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
 }
 sslcli := &http.Client{Transport: tr}
 ctx := context.TODO()
 ctx = context.WithValue(ctx, oauth2.HTTPClient, sslcli)

 state := r.FormValue("state")
 if state != oauthStateString {
  log.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
  http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
  return
 }
 log.Println("state:", state)

 code := r.FormValue("code")
 log.Println("code: ", code)
 token, err := HydraOauthConfig.Exchange(ctx, code)
 if err != nil {
  log.Println("Code exchange failed with:", err)
  http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
  return
 }

 TokenMsg := "<p>Token Info</p>"
 TokenMsg += fmt.Sprintf("token.AccessToken : %s \n", token.AccessToken)
 TokenMsg += fmt.Sprintf("token.TokenType : %s \n", token.TokenType)
 TokenMsg += fmt.Sprintf("token.RefreshToken : %s \n", token.RefreshToken)
 TokenMsg += fmt.Sprintf("token.Expiry : %s \n", token.Expiry)
 TokenMsg += fmt.Sprintf("token Exra id_token : %s \n", token.Extra("id_token"))
 TokenMsg += fmt.Sprintf("token Exra scope : %s \n", token.Extra("scope"))

 log.Println(TokenMsg)

 log.Println("===========all token==========")
 log.Println("token: ", token)

 log.Println("Authentication token.... ")
 client := HydraOauthConfig.Client(ctx, token)
 resp, err := client.Get("https://openid.hydra:9001/")
 if err != nil {
  log.Println(err)
 } else {
  log.Println("Authentication successful !!")
 }
 defer resp.Body.Close()

 // show succes page
 msg := "<p><strong>Success!</strong></p>"
 msg += "<p>You are authenticated and can now return to the CLI.</p>"
 msg += strings.ReplaceAll(TokenMsg, "\n", "<p>")

 fmt.Fprintf(w, msg)

 //response, err := http.Get("https://openid.hydra:9001/userinfo?access_token=" + token.AccessToken)
 //defer response.Body.Close()
 //contents, err := ioutil.ReadAll(response.Body)
 //fmt.Fprintf(w, "Content: %s\n", contents)
}


Try https://t.tt Now can run finish all step.



hydra.rest

###
@audience = audience=
@max_age = max_age=0
@nonce = nonce=kwhqocyluutsstfouosxluqc
@prompt = prompt=

@response_type = response_type=code
@state = state=gczxkznmjkrksgytsemvwgkf

@client_id = client_id=auth-code-client
@scope = scope=openid+offline+photos.read
@redirect_url = redirect_url=https%3A%2F%2Ft.tt%3A9010%2Fcallback

@auth-tailpart = {{audience}}&{{max_age}}&{{nonce}}&{{prompt}}
@9001_auth = https://openid.hydra:9001/oauth2/auth?

### get hydra login page
Get {{9001_auth}}&{{client_id}}&{{redirect_url}}&{{scope}}&{{response_type}}&{{state}}&{{auth-tailpart}}

###
//提醒:csrf可以不更新,challenge一定要更新
@9020_login = http://192.168.99.100:9020/login
@9020_consent = http://192.168.99.100:9020/consent
@_csrf1 = Gxa6Hip4-J_A3L2kpRc72Iclw_Ql8eIcQiTc
@login_challenge = bc55b64985f1400b90a2c2741f8780f2
@email = foo@bar.com
@password = foobar

### get login
GET https://192.168.99.100:9002/oauth2/auth/requests/login?login_challenge={{login_challenge}}

### login
#POST {{9020_login}}
#Content-Type: application/x-www-form-urlencoded

#_csrf={{_csrf1}}
#&challenge={{login_challenge}}
#&email={{email}}
#&password={{password}}

### accept login
PUT https://192.168.99.100:9002/oauth2/auth/requests/login/accept?login_challenge={{login_challenge}}
Content-Type: application/json

{
  "subject": "foo@bar.com",
  "remember": false,
  "remember_for": 3600
}

@login_verifier = login_verifier=1025ccb8109047668715c8162459d6de

### get conent
GET {{9001_auth}}{{login_verifier}}&{{client_id}}&{{redirect_url}}&{{scope}}&{{response_type}}&{{state}}&{{auth-tailpart}}

###
@consent_challenge = d23b6822d88842078a0d83677e8709a8
@_csrf2 = PLSPrz8R-GqmzKwgMtNus3LiX-p9Oh0QaLnQ

### requests consent
###GET {{9020_consent}}?consent_challenge={{consent_challenge}}


### get conent scope
GET https://192.168.99.100:9002/oauth2/auth/requests/consent?consent_challenge={{consent_challenge}}

@submit = Allow access

### accept conent scope
PUT https://192.168.99.100:9002/oauth2/auth/requests/consent/accept?consent_challenge={{consent_challenge}}
Content-Type: application/json

{
  "grant_scope": ["openid", "photos.read"],
  "session": {
    "access_token": { "foo": "bar" },
    "id_token": { "baz": "bar" }
  }
}

@consent_verifier = consent_verifier=ed04b20447c343338e9000b2db640f3c
### get auth token
GET {{9001_auth}}{{consent_verifier}}&{{client_id}}&{{redirect_url}}&{{scope}}&{{response_type}}&{{state}}&{{auth-tailpart}}
### http://192.168.99.100:4444/oauth2/auth?audience=&client_id=auth-code-client&consent_verifier=a643ae2e056543fabbd8d6f747e8a30c&max_age=0&nonce=chscixgzceuosfcocvvmjngj&prompt=&redirect_uri=http%3A%2F%2F127.0.0.1%3A5555%2Fcallback&response_type=code&scope=openid+offline&state=oplovvughuyzixqdvxnortrq

@token= xLPcJ3tobDqGUDxIVTxWt2p7w_odZSV22IAlUf5QPZU.YD6R_xKQ2ldCLbEV7mmc01E6ZLzemzdEC5H4-otTMPg
### userinfo
GET https://openid.hydra:9001/userinfo
Authorization: Bearer {{token}}
### introspect
POST https://openid.hydra:9002/oauth2/introspect
Content-Type: application/x-www-form-urlencoded

token={{token}}
&scope=openid+photos.read

###
GET https://openid.hydra:9002/oauth2/auth/sessions/consent?subject=foo@bar.com HTTP/1.1

PS:&scope=openid+photos.read can remove.

PS:
Here REST Client still return login page. go main server error log:

Post https://openid.hydra:9001/oauth2/token: x509: certificate signed by unknown authority


This is Go Server problem. See main.go Line:55-61 82-94 Fix this problem.




========== old ==========

3、Now have problem is token user. When you run *A, try to open web broswer. http://192.168.99.100:9010 then click "Authorize application" get error.
Because "Authorize application" still is 127.0.0.1. No way to change. So copy Link change it.


https://192.168.99.100:9001/oauth2/auth?audience=&client_id=auth-code-client&max_age=0&nonce=ylnybhabgcjllcxbfvhfjdfe&prompt=&redirect_uri=http%3A%2F%2F192.168.99.100%3A9010%2Fcallback&response_type=code&scope=openid+offline+photos.read&state=shqjytubxbrzqwtiskwwpfdp

Copy fix link to go. Fllow website.


4、The Big problem is Allow access only get error. Can't know why.


Rest Client || visual studio code

Even by step to run. Still get error......

OpenID grant_type

https://blog.yorkxin.org/2013/09/30/oauth2-3-endpoints.html

Grant Type
Grant Type 透過 grant_type 參數來指定,其值定義如下:

值 意義
authorization_code 用 Authorization Code 求 Access Token (Authorization Code Grant Flow)。
password 用 Resorce Owner Password Credentials 求 Access Token (Resource Owner Password Credentials Grant Flow)。
client_credentials 用 Client Credentials 求 Access Token (Client Credentials Grant Flow)。
refresh_token 用 Refresh Token 換發 Access Token。

OpenID hydra dex

F... Now follow step run, Get level=error msg="An error occurred" debug="No CSRF value available in the session cookie" description="The request is not allowed" error=request_forbidden hint="You are not allowed to perform this action."

If you run same broswer and restart docker or clear cookie, do many way. Just try broswer private mode.



Try dex docker or binary failed, it's be pass.

Hydra docker-compose

1、get https://github.com/ory/hydra



docker-compose -f quickstart.yml -f quickstart-postgres.yml up --build

注意 quickstart.yml



run docker on host or run binary on host. hydra 5 minutes demo "IP Used" is 127.0.0.1



version: '3'

services:

  hydra:
    image: oryd/hydra:latest
    ports:
      - "4444:4444" # Public port
      - "4445:4445" # Admin port
      - "5555:5555" # Port for hydra token user
    command:
      serve all --dangerous-force-http
    environment:
      - URLS_SELF_ISSUER=http://127.0.0.1:4444
      - URLS_CONSENT=http://127.0.0.1:3000/consent
      - URLS_LOGIN=http://127.0.0.1:3000/login
      - URLS_LOGOUT=http://127.0.0.1:3000/logout
      - DSN=memory
      - SECRETS_SYSTEM=youReallyNeedToChangeThis
      - OIDC_SUBJECT_TYPES_SUPPORTED=public,pairwise
      - OIDC_SUBJECT_TYPE_PAIRWISE_SALT=youReallyNeedToChangeThis
    restart: unless-stopped

  consent:
    environment:
      - HYDRA_ADMIN_URL=http://hydra:4445
    image: oryd/hydra-login-consent-node:latest
    ports:
      - "3000:3000"
    restart: unless-stopped


run VM or real server is real ip. Ex: 192.168.99.100 (docker-machine)




version: '3'

services:

  hydra:
    image: oryd/hydra:latest
    ports:
      - "4444:4444" # Public port
      - "4445:4445" # Admin port
      - "5555:5555" # Port for hydra token user
    command:
      serve all --dangerous-force-http
    environment:
      - URLS_SELF_ISSUER=http://192.168.99.100:4444
      - URLS_CONSENT=http://192.168.99.100:3000/consent
      - URLS_LOGIN=http://192.168.99.100:3000/login
      - URLS_LOGOUT=http://192.168.99.100:3000/logout
      - DSN=memory
      - SECRETS_SYSTEM=youReallyNeedToChangeThis
      - OIDC_SUBJECT_TYPES_SUPPORTED=public,pairwise
      - OIDC_SUBJECT_TYPE_PAIRWISE_SALT=youReallyNeedToChangeThis
    restart: unless-stopped

  consent:
    environment:
      - HYDRA_ADMIN_URL=http://hydra:4445
    image: oryd/hydra-login-consent-node:latest
    ports:
      - "3000:3000"
    restart: unless-stopped


If have cors problems. see https://github.com/ory/hydra/blob/master/quickstart-cors.yml


Check hydra OpenID startup or not 確認是否正常啟動


http://192.168.99.100:4444/.well-known/jwks.json  


Create clients


Download hydra binary.

https://www.ory.sh/docs/next/hydra/install#download-binaries
https://github.com/ory/hydra/releases
https://github.com/ory/hydra/releases/tag/v1.0.0-rc.15

PS: Maybe version renew, so try to get best new.


hydra clients create --endpoint http://192.168.99.100:4445/ --id auth-code-client --secret secret --grant-types authorization_code,refresh_token --response-types code,id_token --scope openid,offline --callbacks http://127.0.0.1:5555/callback

! new version use endpoint, different before auth-url and token-url, But I think you still can use old way... Maybe

! scope "openid,offline" next step must use same. So scope is definend by yourself.

Thanks https://dotblogs.com.tw/liguobao/2018/12/30/132746


Check clients 查看clients


hydra clients list --endpoint http://192.168.99.100:4445 


Emu all step OpenID


Fllow website that run command pop website. If no pop, http://127.0.0.1:5555/



hydra token user --client-id auth-code-client --client-secret secret --endpoint http://192.168.99.100:4444 --port 5555 --scope openid,offline

This step will run server on port 5555

! here scope "openid,offline" must same before create.








Get userinfo. Copy Access Token replace string after Bearer



curl -X GET http://192.168.99.100:4444/userinfo -H 'Accept: application/json' -H 'Authorization: Bearer MmadDHs3VdWC7LZTIdBKUHyzgsWHe2XbzHpwjKrF7Rs.tXlg7rShEEbkcczNWJGS84sIvokTF6Ae7bhSQZfHMgA' 

Get json
{"sid":"c7d5665b-76e7-475a-95a8-cc521352663b","sub":"foo@bar.com"}


Modify edit add userinfo info.


https://github.com/ory/hydra-login-consent-node/blob/master/routes/login.js
subject: 'foo@bar.com', -> subject: 'foo@bar.com-success',


This docker test
1. docker ps
2. get oryd/hydra-login-consent-node:v1.0.0-rc.10 containerid
3. docker exec -it containerid /bin/sh
4. vi bin/www change port 3000 - > 3001
5. vi routes/login.js subject: 'foo@bar.com', => subject: 'foo@bar.com--success',
5. node ./bin/www &
6. ps
7. kill old node (be exit container)
8. docker exec -it containerid /bin/sh
9. vi bin/www change port 3001 - > 3000
10. node ./bin/www &
11. kill old node (be exit container)
12. docker exec -it containerid /bin/sh
13. netstat -nlp (check port 3000)


====================
https://mileschou.github.io/auth-notes/src/hydra/user-login-and-consent-flow.html#oauth-2-0-%E8%88%87-open-id-connect
====================
https://dotblogs.com.tw/liguobao/2018/12/30/132746
OAUTH2_ISSUER_URL hydra所在的地址
OAUTH2_CONSENT_URL 授权页面地址
OAUTH2_LOGIN_URL 登录页面地址

XX应用请求授权
-> 跳转到OAUTH2_LOGIN_URL地址
-> 登录成功
->跳转到OAUTH2_CONSENT_URL授权页面
-> 授权成功
->回调XX应用地址并且返回相关授权code/token
-> XX应用使用code/token获取用户信息或者其他操作

[轉]鋪柏油路

我是退休的營造工程師,我自己也開營造廠。 做營造的人不會穿皮鞋,就算工程師>工地主任>工程部經理,真的在做營造工程的只會穿運動鞋/安全鞋,很少機會去穿西裝皮鞋,說不好聽的你去看上酒店喝酒的一線營造業還是只穿運動鞋(當年真是天天花天酒地除了星期日)。
台灣的工程常常都是做完賺經驗,就是前面的設計仿歐美失敗,然後失敗中學經驗再修改,政府很多土木工程都是從設計就不是完美,大部分馬路自今還是設計缺陷,沒有因台灣環境去真的更改,還是沿用古老的傳統。

營造業基本上有在標政府工程的大概都知道工程的黑幕,高雄從謝長廷開始就是大黑特黑,不是陳菊。重點是不是他們的人你有錢還標不了工程。
懂理論與實際工程經驗不一樣,確實 料 一直是營造工程最真實的問題,不是一天兩天是3X年前我第一次進工地就知道的問題,另外 3cm的柏油做不起來很快會龜裂不耐用,最低都是5cm沒有3cm的。
柏油路 最重要的除了是原料之外還有路基,下面的給配有無確實的夯實才是耐用王道,因為載力是往下傳;破壞力是往前延伸。

一般馬路與高速公路的使用方式不同,高速公路是高速行駛在上面說最庶民語言就是飛過去,馬路是碾壓在上面,因為各種車子的起步與慢速最傷馬路,所以設計要不同。
香港的馬路有雙層巴士,這是數量最多的大型車輛,當然其他連結車 貨車都有。但是單論台灣 香港一般馬路最多的大型車就是公車,兩地的馬路除了工程破壞從鋪不論之外,香港的馬路真的就是比台灣好比台灣耐用,我看1X年了到今年2019年5月還再看有公車行駛的山坡地他們怎麼鋪馬路,說真的台灣做不到。

香港的馬路基本配置法(大部分的馬路皆一樣),基本有三層,原始層(這部分做得很確實夯實)/路基(標準30cm)/柏油(30cm),只要看到他們挖馬路的時候,挖起來的柏油就是30cm,大部分的馬路。有部分馬路統一不用柏油例如公車站,這就要用剛性路面(硬),就是台灣收費站的區域你不會看到柏油的原因<<<<這才是重點 重點 重點。
香港我有住的地方是一般街市(公屋/菜市場),我附近的馬路我知道的就已經10年沒重新鋪過,路還是一樣的平,只是退色會變灰白色。

李四川副市長是真的懂工程的人,以前他在台北市的時候,我剛好在做北市X期汙水工程的工地主任。















您好、我做過柏油工程及自來水管工程及當過水泥預拌混凝土司機,這3個工作共10幾年。 我對柏油路有一些看法。 您影片中只是一小部分原因,還有更多原因,那我簡單分享一下,讓大眾了解為何柏油路面無法鋪好。 1: 柏油路面下有很多工程。如自來水、電信、寬頻、瓦斯、第四台等管線,在做這些工程時會挖開柏油路面,把這些管線埋在地底1米-1米多不等,重點在於「回填」,地底的紮實度,直接影響路面狀況。 2: 依工程規定必須叫水泥預拌車用(clsm水泥回填),地底才會紮實,大車開過才不會塌陷,及水泥不會被雨水滲透流失。 可以試想一下,下面土是軟的、上面是柏油(就算上面鋪再厚),地底還是軟的,大車開過或下大雨後,導致柏油路面坍塌或地底被雨水掏空後直接柏油路面破洞。 很多工程都未依規定,直接「原土」回填,為了省「水泥」的錢,相當可觀唷。 或原土回填後上面鋪薄薄的水泥拍照📷,來騙公家機關(其實官官相護就是收回扣)。 或用品質很差的clsm(水泥)來回填,跟如您影片中很差的柏油品質一樣。