text:
---
title: "Asynchronous I/O for External Data Access"
nav-title: "Async I/O"
nav-parent_id: streaming_operators
nav-pos: 60
---

* ToC
{:toc}

This page explains the use of Flink's API for asynchronous I/O with external data stores.
For users not familiar with asynchronous or event-driven programming, an article about Futures and
event-driven programming may be useful preparation.

Note: Details about the design and implementation of the asynchronous I/O utility can be found in the proposal and design document
[FLIP-12: Asynchronous I/O Design and Implementation](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=65870673).

## The need for Asynchronous I/O Operations

When interacting with external systems (for example when enriching stream events with data stored in a database), one needs to take care
that communication delay with the external system does not dominate the streaming application's total work.

Naively accessing data in the external database, for example in a `MapFunction`, typically means **synchronous** interaction:
A request is sent to the database and the `MapFunction` waits until the response has been received. In many cases, this waiting
makes up the vast majority of the function's time.

Asynchronous interaction with the database means that a single parallel function instance can handle many requests concurrently and
receive the responses concurrently. That way, the waiting time can be overlayed with sending other requests and
receiving responses. At the very least, the waiting time is amortized over multiple requests. This leads in most cased to much higher
streaming throughput.

*Note:* Improving throughput by just scaling the `MapFunction` to a very high parallelism is in some cases possible as well, but usually
comes at a very high resource cost: Having many more parallel MapFunction instances means more tasks, threads, Flink-internal network
connections, network connections to the database, buffers, and general internal bookkeeping overhead.

## Prerequisites

As illustrated in the section above, implementing proper asynchronous I/O to a database (or key/value store) requires a client
to that database that supports asynchronous requests. Many popular databases offer such a client.

In the absence of such a client, one can try and turn a synchronous client into a limited concurrent client by creating
multiple clients and handling the synchronous calls with a thread pool. However, this approach is usually less
efficient than a proper asynchronous client.

## Async I/O API

Flink's Async I/O API allows users to use asynchronous request clients with data streams. The API handles the integration with
data streams, well as handling order, event time, fault tolerance, etc.

Assuming one has an asynchronous client for the target database, three parts are needed to implement a stream transformation
with asynchronous I/O against the database:

  - An implementation of `AsyncFunction` that dispatches the requests
  - A *callback* that takes the result of the operation and hands it to the `ResultFuture`
  - Applying the async I/O operation on a DataStream as a transformation

The following code example illustrates the basic pattern:

{% highlight java %}
// This example implements the asynchronous request and callback with Futures that have the
// interface of Java 8's futures (which is the same one followed by Flink's Future)

/**
 * An implementation of the 'AsyncFunction' that sends requests and sets the callback.
 */
class AsyncDatabaseRequest extends RichAsyncFunction<String, Tuple2<String, String>> {

    /** The database specific client that can issue concurrent requests with callbacks */
    private transient DatabaseClient client;

    @Override
    public void open(Configuration parameters) throws Exception {
        client = new DatabaseClient(host, post, credentials);
    }

    @Override
    public void close() throws Exception {
        client.close();
    }

    @Override
    public void asyncInvoke(String key, final ResultFuture<Tuple2<String, String>> resultFuture) throws Exception {

        // issue the asynchronous request, receive a future for result
        final Future<String> result = client.query(key);

        // set the callback to be executed once the request by the client is complete
        // the callback simply forwards the result to the result future
        CompletableFuture.supplyAsync(new Supplier<String>() {

            @Override
            public String get() {
                try {
                    return result.get();
                } catch (InterruptedException | ExecutionException e) {
                    // Normally handled explicitly.
                    return null;
                }
            }
        }).thenAccept( (String dbResult) -> {
            resultFuture.complete(Collections.singleton(new Tuple2<>(key, dbResult)));
        });
    }
}

// create the original stream
DataStream<String> stream = ...;

// apply the async I/O transformation
DataStream<Tuple2<String, String>> resultStream =
    AsyncDataStream.unorderedWait(stream, new AsyncDatabaseRequest(), 1000, TimeUnit.MILLISECONDS, 100);

{% endhighlight %}

{% highlight scala %}
/**
 * An implementation of the 'AsyncFunction' that sends requests and sets the callback.
 */
class AsyncDatabaseRequest extends AsyncFunction[String, (String, String)] {

    /** The database specific client that can issue concurrent requests with callbacks */
    lazy val client: DatabaseClient = new DatabaseClient(host, post, credentials)

    /** The context used for the future callbacks */
    implicit lazy val executor: ExecutionContext = ExecutionContext.fromExecutor(Executors.directExecutor())

    override def asyncInvoke(str: String, resultFuture: ResultFuture[(String, String)]): Unit = {

        // issue the asynchronous request, receive a future for the result
        val resultFutureRequested: Future[String] = client.query(str)

        // set the callback to be executed once the request by the client is complete
        // the callback simply forwards the result to the result future
        resultFutureRequested.onSuccess {
            case result: String => resultFuture.complete(Iterable((str, result)))
        }
    }
}

// create the original stream
val stream: DataStream[String] = ...

// apply the async I/O transformation
val resultStream: DataStream[(String, String)] =
    AsyncDataStream.unorderedWait(stream, new AsyncDatabaseRequest(), 1000, TimeUnit.MILLISECONDS, 100)

{% endhighlight %}

**Important note**: The `ResultFuture` is completed with the first call of `ResultFuture.complete`.
All subsequent `complete` calls will be ignored.

The following two parameters control the asynchronous operations:

  - **Timeout**: The timeout defines how long an asynchronous request may take before it is considered failed. This parameter
    guards against dead/failed requests.

  - **Capacity**: This parameter defines how many asynchronous requests may be in progress at the same time.
    Even though the async I/O approach leads typically to much better throughput, the operator can still be the bottleneck in
    the streaming application. Limiting the number of concurrent requests ensures that the operator will not
    accumulate an ever-growing backlog of pending requests, but that it will trigger backpressure once the capacity
    is exhausted.

### Timeout Handling

When an async I/O request times out, by default an exception is thrown and job is restarted.
If you want to handle timeouts, you can override the `AsyncFunction#timeout` method.

### Order of Results

The concurrent requests issued by the `AsyncFunction` frequently complete in some undefined order, based on which request finished first.
To control in which order the resulting records are emitted, Flink offers two modes:

  - **Unordered**: Result records are emitted as soon as the asynchronous request finishes.
    The order of the records in the stream is different after the async I/O operator than before.
    This mode has the lowest latency and lowest overhead, when used with *processing time* as the basic time characteristic.
    Use `AsyncDataStream.unorderedWait(...)` for this mode.

  - **Ordered**: In that case, the stream order is preserved. Result records are emitted in the same order as the asynchronous
    requests are triggered (the order of the operators input records). To achieve that, the operator buffers a result record
    until all its preceding records are emitted (or timed out).
    This usually introduces some amount of extra latency and some overhead in checkpointing, because records or results are maintained
    in the checkpointed state for a longer time, compared to the unordered mode.
    Use `AsyncDataStream.orderedWait(...)` for this mode.

### Event Time

When the streaming application works with [event time]({{ site.baseurl }}/dev/event_time.html), watermarks will be handled correctly by the
asynchronous I/O operator. That means concretely the following for the two order modes:

  - **Unordered**: Watermarks do not overtake records and vice versa, meaning watermarks establish an *order boundary*.
    Records are emitted unordered only between watermarks.
    A record occurring after a certain watermark will be emitted only after that watermark was emitted.
    The watermark in turn will be emitted only after all result records from inputs before that watermark were emitted.

    That means that in the presence of watermarks, the *unordered* mode introduces some of the same latency and management
    overhead as the *ordered* mode does. The amount of that overhead depends on the watermark frequency.

  - **Ordered**: Order of watermarks an records is preserved, just like order between records is preserved. There is no
    significant change in overhead, compared to working with *processing time*.

Please recall that *Ingestion Time* is a special case of *event time* with automatically generated watermarks that
are based on the sources processing time.

### Fault Tolerance Guarantees

The asynchronous I/O operator offers full exactly-once fault tolerance guarantees. It stores the records for in-flight
asynchronous requests in checkpoints and restores/re-triggers the requests when recovering from a failure.

### Implementation Tips

For implementations with *Futures* that have an *Executor* (or *ExecutionContext* in Scala) for callbacks, we suggests to use a `DirectExecutor`, because the
callback typically does minimal work, and a `DirectExecutor` avoids an additional thread-to-thread handover overhead. The callback typically only hands
the result to the `ResultFuture`, which adds it to the output buffer. From there, the heavy logic that includes record emission and interaction
with the checkpoint bookkeeping happens in a dedicated thread-pool anyways.

A `DirectExecutor` can be obtained via `org.apache.flink.runtime.concurrent.Executors.directExecutor()` or
`com.google.common.util.concurrent.MoreExecutors.directExecutor()`.

### Caveat

**The AsyncFunction is not called Multi-Threaded**

A common confusion that we want to explicitly point out here is that the `AsyncFunction` is not called in a multi-threaded fashion.
There exists only one instance of the `AsyncFunction` and it is called sequentially for each record in the respective partition
of the stream. Unless the `asyncInvoke(...)` method returns fast and relies on a callback (by the client), it will not result in
proper asynchronous I/O.

For example, the following patterns result in a blocking `asyncInvoke(...)` functions and thus void the asynchronous behavior:

  - Using a database client whose lookup/query method call blocks until the result has been received back

  - Blocking/waiting on the future-type objects returned by an asynchronous client inside the `asyncInvoke(...)` method

{% top %}


text:
<?php
include_once "lib/functions.php";

if(isset ($_POST['propuesta'])){

	$propuesta=$_POST['propuesta'];
	$usuario=$_POST['usuario_id'];

	try{
	$conn = new PDO('mysql:host='.MYSQL_HOST.';dbname='.MYSQL_DB, MYSQL_USER, MYSQL_PASS);
	$consulta = "SELECT propuesta_voto FROM prog_likes_propuesta
	WHERE propuesta_id = ".$propuesta." AND usuario_id = ".$usuario.";";
	$result = $conn->prepare($consulta);
	$result->execute();
	foreach($result as $res){
		$propuesta_voto=$res['propuesta_voto'];
	}

	if ($propuesta_voto==1){
		$consulta="DELETE FROM prog_likes_propuesta WHERE propuesta_id = ".$propuesta." AND usuario_id = ".$usuario.";";
		listar($consulta);
		$suma="UPDATE prog_propuestas SET sum_likes=sum_likes-1, positivos=positivos-1 WHERE id = ".$propuesta.";";
		listar($suma);

	}if ($propuesta_voto==-1){
		$consulta="DELETE FROM prog_likes_propuesta WHERE propuesta_id = ".$propuesta." AND usuario_id = ".$usuario.";";
		listar($consulta);
		$suma="UPDATE prog_propuestas SET sum_likes = sum_likes+1, negativos = negativos-1 WHERE id = ".$propuesta.";";
		listar($suma);

	}

	$consulta = "SELECT sum_likes FROM prog_propuestas WHERE id = ".$propuesta.";";
	$result = $conn->prepare($consulta);
	$result->execute();
	//Se crea array vacío
	$output= array();
	foreach($result as $res){
		$like=$res['sum_likes'];
	}
	//Array serializado para pasar datos con json.
	$output[] = array('sum_likes' => $like);
	echo json_encode($output);

	}catch(PDOException $e ){
		echo $e -> getMessage();
	}

}

redpajama_set_name: RedPajamaGithub


text:
require 'rails_helper'

describe LeaveTimeSummaryService do
  before { Timecop.freeze(Time.zone.local(2018, 1, 2)) }
  let!(:manager) { create(:user, :manager) }
  let!(:user) { create(:user, :employee, join_date: Time.zone.local(2018, 1, 2)) }
  let!(:user2) { create(:user, :employee, join_date: Time.zone.local(2016, 1, 2)) }

  describe 'summary total leave_time' do
    context 'same leave type' do
      let(:start_time) { Time.zone.local(2018, 1, 5, 9, 30) }
      let(:end_time) { Time.zone.local(2018, 1, 10, 18, 30) }
      it 'should calculate total leave' do
        leave_application = create(:leave_application, :personal, user: user, start_time: start_time, end_time: end_time).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, :personal, user: user2, start_time: start_time, end_time: end_time).reload
        leave_application.approve!(manager)
        summary = LeaveTimeSummaryService.new(Date.current.year, Date.current.month).summary
        expect(summary[user.id]['annual']).to eq 32
        expect(summary[user2.id]['annual']).to eq 32
      end
    end

    context 'different leave type' do
      let(:personal_start_time) { Time.zone.local(2018, 1, 18, 9, 30) }
      let(:personal_end_time) { Time.zone.local(2018, 1, 31, 18, 30) }
      it 'should calculate total leave times for different leave type' do
        leave_application = create(:leave_application, user: user, start_time: personal_start_time, end_time: personal_end_time).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, user: user2, start_time: personal_start_time, end_time: personal_end_time).reload
        leave_application.approve!(manager)
        summary = LeaveTimeSummaryService.new(2018, 1).summary
        expect(summary[user.id]['annual']).to eq 56
        expect(summary[user.id]['personal']).to eq 24
        expect(summary[user2.id]['annual']).to eq 80
      end
    end

    context 'start time and end time in different month' do
      let(:start_time) { Time.zone.local(2018, 1, 25, 10, 30) }
      let(:start_time2) { Time.zone.local(2018, 1, 30, 9, 30) }
      let(:end_time) { Time.zone.local(2018, 1, 29, 18, 30) }
      let(:end_time2) { Time.zone.local(2018, 2, 9, 18, 30) }
      it 'should calculate total sick leave times in specified month' do
        leave_application = create(:leave_application, :halfpaid_sick, user: user, start_time: start_time, end_time: end_time).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, :halfpaid_sick, user: user, start_time: start_time2, end_time: end_time2).reload
        leave_application.approve!(manager)
        summary = LeaveTimeSummaryService.new(2018, 1).summary
        expect(summary[user.id]['halfpaid_sick']).to eq 39
        summary = LeaveTimeSummaryService.new(2018, 2).summary
        expect(summary[user.id]['halfpaid_sick']).to eq 56
      end

      it 'should calculate total personal leave times in specified month' do
        create(:leave_time, :bonus, user: user, quota: 8, usable_hours: 8)
        leave_application = create(:leave_application, :personal, user: user, start_time: start_time, end_time: end_time).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, :personal, user: user, start_time: start_time2, end_time: end_time2).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, :personal, user: user2, start_time: start_time, end_time: end_time).reload
        leave_application.approve!(manager)
        leave_application = create(:leave_application, :personal, user: user2, start_time: start_time2, end_time: end_time2).reload
        leave_application.approve!(manager)
        summary = LeaveTimeSummaryService.new(2018, 1).summary
        expect(summary[user.id]['bonus']).to eq 8
        expect(summary[user.id]['annual']).to eq 31
        expect(summary[user2.id]['annual']).to eq 39
        summary = LeaveTimeSummaryService.new(2018, 2).summary
        expect(summary[user.id]['annual']).to eq 25
        expect(summary[user.id]['personal']).to eq 31
        expect(summary[user2.id]['annual']).to eq 41
        expect(summary[user2.id]['personal']).to eq 15
      end
    end
  end
end


text:
require "test_helper"

class EditionTaggerTest < ActiveSupport::TestCase
  setup do
    @logger = stub("logger")
    @logger.stubs(:info)
  end

  def mock_registerer(slug)
    mock_slug_registerer = stub("PublishedSlugRegisterer")
    PublishedSlugRegisterer.stubs(:new)
                           .with(@logger, [slug])
                           .returns(mock_slug_registerer)
    mock_slug_registerer.expects(:run).returns(true)
  end

  test "should assign tag to a single Edition" do
    edition = FactoryGirl.create(:edition, state: :published)
    mock_registerer(edition.slug)

    EditionTagger.new([{slug: edition.slug, tag: "foo"}], @logger).run

    assert_equal ["foo"], edition.published_edition.browse_pages
  end

  test "should assign tags to draft edition when no published edition" do
    draft_edition = FactoryGirl.create(:edition,
      state: :draft, slug: "/a-slug")
    mock_registerer("/a-slug")

    EditionTagger.new([{slug: "/a-slug", tag: "foo"}], @logger).run
    draft_edition.reload

    assert_equal ["foo"], draft_edition.browse_pages
  end

  test "should assign tags to published and draft Editions" do
    published_edition = FactoryGirl.create(:edition,
      state: :published, slug: "/a-slug")
    draft_edition = FactoryGirl.create(:edition,
      state: :draft, slug: "/a-slug",
      panopticon_id: published_edition.panopticon_id)
    archived_edition = FactoryGirl.create(:edition,
      state: :archived, slug: "/a-slug",
      panopticon_id: published_edition.panopticon_id)
    mock_registerer("/a-slug")

    EditionTagger.new([{slug: "/a-slug", tag: "foo"}], @logger).run
    archived_edition.reload
    draft_edition.reload
    published_edition.reload

    assert_equal [], archived_edition.browse_pages
    assert_equal ["foo"], draft_edition.browse_pages
    assert_equal ["foo"], published_edition.browse_pages
  end

  test "should not add duplicate tags" do
    edition = FactoryGirl.create(:edition, state: :published, browse_pages: ["foo"])
    mock_registerer(edition.slug)

    EditionTagger.new([{slug: edition.slug, tag: "foo"}], @logger).run

    assert_equal ["foo"], edition.published_edition.browse_pages
  end

  test "should add primary tags first" do
    edition = FactoryGirl.create(:edition, state: :published, browse_pages: ["foo"])
    mock_registerer(edition.slug)

    EditionTagger.new([{slug: edition.slug, tag: "bar", primary: "TRUE"}], @logger).run

    assert_equal ["bar", "foo"], edition.published_edition.browse_pages
  end

  test "should add non-primary tags last" do
    edition = FactoryGirl.create(:edition, state: :published, browse_pages: ["foo"])
    mock_registerer(edition.slug)

    EditionTagger.new([{slug: edition.slug, tag: "bar", primary: "FALSE"}], @logger).run

    assert_equal ["foo", "bar"], edition.published_edition.browse_pages
  end

  test "should error on typos in the `primary` column" do
    err = assert_raises(RuntimeError) {
      EditionTagger.new([{slug: "a-slug", tag: "bar", primary: "FASLE"}], @logger).run
    }
    assert_equal %{Invalid value for `primary`: FASLE}, err.message
  end
end


text:
<!doctype html>

        <title>Test for Pause</title>

        <meta charset="utf-8" />

        <link rel="stylesheet" href="../dist/proteic.css">


text:
            <a href="<?php base_url(); ?>">Home

            Pelaporan Pajak

                         Pelaporan Pajak

                    No. Order

                        <input id="order_no" readonly type="text" class="FormElement form-control ">

                    No. Bayar

                        <input id="payment_key" readonly type="text" class="FormElement form-control ">

                    Jenis Pajak

                        <input id="jenis_pajak" readonly type="text" class="FormElement form-control ">

                    NPWPD

                        <input id="npwd" readonly type="text" class="FormElement form-control ">

                    Nama Merk Dagang

                        <input id="company_brand" readonly type="text" class="FormElement form-control ">

                    Alamat

                        <input id="brand_address_name" readonly type="text" class="FormElement form-control ">

                    Periode

                        <input id="finance_period_code" readonly type="text" class="FormElement form-control ">

                    Masa Pajak

                        <input id="start_date_txt" readonly type="text" class="FormElement form-control ">

                        <input id="end_date_txt" readonly type="text" class="FormElement form-control ">

                    Total Transaksi

                        <input style="text-align: right;" id="total_trans_amount" readonly type="text" class="FormElement form-control ">

                    Total Pajak

                        <input style="text-align: right;" id="total_vat_amount" readonly type="text" class="FormElement form-control ">

                    Tanggal Jatuh Tempo

                        <input id="due_date" readonly type="text" class="FormElement form-control ">

                    Denda

                        <input style="text-align: right;" id="total_penalty_amount" readonly type="text" class="FormElement form-control ">

                    Dasar Pengenaan

                        <input style="text-align: right;" id="debt_vat_amt" readonly type="text" class="FormElement form-control ">

                    Bunga (Pasal 65 ayat(2))

                        <input style="text-align: right;" id="db_interest_charge" readonly type="text" class="FormElement form-control ">

                    Kenaikan (Pasal 65 ayat (3))

                        <input style="text-align: right;" id="db_increasing_charge" readonly type="text" class="FormElement form-control ">

                        Print No. Bayar
                        Kembali

    <input type="hidden" id="TEMP_ELEMENT_ID" value="<?php echo $this->input->post('ELEMENT_ID'); ?>" />
    <input type="hidden" id="TEMP_PROFILE_TYPE" value="<?php echo $this->input->post('PROFILE_TYPE'); ?>" />
    <input type="hidden" id="TEMP_P_W_DOC_TYPE_ID" value="<?php echo $this->input->post('P_W_DOC_TYPE_ID'); ?>" />
    <input type="hidden" id="TEMP_P_W_PROC_ID" value="<?php echo $this->input->post('P_W_PROC_ID'); ?>" />
    <input type="hidden" id="TEMP_USER_ID" value="<?php echo $this->input->post('USER_ID'); ?>" />
    <input type="hidden" id="TEMP_FSUMMARY" value="<?php echo $this->input->post('FSUMMARY'); ?>" />

    <input type="hidden" id="CURR_DOC_ID" value="<?php echo $this->input->post('CURR_DOC_ID'); ?>">
    <input type="hidden" id="CURR_DOC_TYPE_ID" value="<?php echo $this->input->post('CURR_DOC_TYPE_ID'); ?>">
    <input type="hidden" id="CURR_PROC_ID" value="<?php echo $this->input->post('CURR_PROC_ID'); ?>">
    <input type="hidden" id="CURR_CTL_ID" value="<?php echo $this->input->post('CURR_CTL_ID'); ?>">
    <input type="hidden" id="USER_ID_DOC" value="<?php echo $this->input->post('USER_ID_DOC'); ?>">
    <input type="hidden" id="USER_ID_DONOR" value="<?php echo $this->input->post('USER_ID_DONOR'); ?>">
    <input type="hidden" id="USER_ID_LOGIN" value="<?php echo $this->input->post('USER_ID_LOGIN'); ?>">
    <input type="hidden" id="USER_ID_TAKEN" value="<?php echo $this->input->post('USER_ID_TAKEN'); ?>">
    <input type="hidden" id="IS_CREATE_DOC" value="<?php echo $this->input->post('IS_CREATE_DOC'); ?>">
    <input type="hidden" id="IS_MANUAL" value="<?php echo $this->input->post('IS_MANUAL'); ?>">
    <input type="hidden" id="CURR_PROC_STATUS" value="<?php echo $this->input->post('CURR_PROC_STATUS'); ?>">
    <input type="hidden" id="CURR_DOC_STATUS" value="<?php echo $this->input->post('CURR_DOC_STATUS'); ?>">
    <input type="hidden" id="PREV_DOC_ID" value="<?php echo $this->input->post('PREV_DOC_ID'); ?>">
    <input type="hidden" id="PREV_DOC_TYPE_ID" value="<?php echo $this->input->post('PREV_DOC_TYPE_ID'); ?>">
    <input type="hidden" id="PREV_PROC_ID" value="<?php echo $this->input->post('PREV_PROC_ID'); ?>">
    <input type="hidden" id="PREV_CTL_ID" value="<?php echo $this->input->post('PREV_CTL_ID'); ?>">
    <input type="hidden" id="SLOT_1" value="<?php echo $this->input->post('SLOT_1'); ?>">
    <input type="hidden" id="SLOT_2" value="<?php echo $this->input->post('SLOT_2'); ?>">
    <input type="hidden" id="SLOT_3" value="<?php echo $this->input->post('SLOT_3'); ?>">
    <input type="hidden" id="SLOT_4" value="<?php echo $this->input->post('SLOT_4'); ?>">
    <input type="hidden" id="SLOT_5" value="<?php echo $this->input->post('SLOT_5'); ?>">
    <input type="hidden" id="MESSAGE" value="<?php echo $this->input->post('MESSAGE'); ?>">
    <input type="hidden" id="PROFILE_TYPE" value="<?php echo $this->input->post('PROFILE_TYPE'); ?>">
    <input type="hidden" id="ACTION_STATUS" value="<?php echo $this->input->post('ACTION_STATUS'); ?>">

<?php
    $this->load->view('workflow/lov_submitter.php');
?>


text:
var fsMod = require('fs');
var pathMod = require('path');
var noptMod = /** @type {!Function} */ (require('nopt'));
var fork = /** @type {!Function} */ (require('child_process').fork);
var exec = /** @type {!Function} */ (require('child_process').exec);

// Need to trick the presubmit script to not complain.
var log = console['log'];

function usage() {
  log('Lovefield Bundler');
  log('Usage:');
  log('  --schema Path of the YAML schema file');
  log('  --namespace Namespace of generated code');
  log('  --ouputdir Output directory (Optional, default to $cwd)');
  log('  --compiler Closure compiler JAR path ');
  log('             (Optional, default to $CLOSURE_COMPILER)');
  log('  --library Closure library path ');
  log('            (Optional, default to $CLOSURE_LIBRARY)');
  log('  --debug <true|false> Generate debug bundle (i.e. non-scrambled)');
  process.exit(1);
}

// Command line options
var knownOpts = {
  'schema': pathMod,
  'namespace': [String],
  'compiler': pathMod,
  'library': [String, null],
  'outputdir': pathMod,
  'debug': [Boolean, null]
};
var args = noptMod(knownOpts);

if (!args.hasOwnProperty('schema') ||
    !args.hasOwnProperty('namespace')) {
  usage();
}

/** @type {string} */
var namespace = args.namespace;

/** @type {string} */
var schemaPath = args.schema;

/** @type {string} */
var outputDir = args.outputdir || process.cwd();

/** @type {string} */
var compilerPath = args.compiler || process.env['CLOSURE_COMPILER'];

/** @type {string} */
var closureDir = args.library || process.env['CLOSURE_LIBRARY'];

if (!(schemaPath && outputDir && compilerPath && closureDir)) {
  usage();
}

var spacPath = pathMod.join(pathMod.resolve(__dirname), '../spac/spac.js');
var spac = fork(
    spacPath,
    [
     '--schema=' + schemaPath,
     '--namespace=' + namespace,
     '--outputdir=' + outputDir
    ]);

spac.on('close', function(code) {
  if (code == 0) {
    runClosure();
  } else {
    log('ERROR: unable to generate code from schema');
  }
});

function runClosure() {
  var namespacePrefix = namespace.replace('.', '_');
  var generatedFiles = [
    namespacePrefix + '_database.js',
    namespacePrefix + '_schema.js',
    namespacePrefix + '_transaction.js'
  ].map(function(fileName) {
    return pathMod.resolve(pathMod.join(outputDir, fileName));
  });

  var root = pathMod.join(pathMod.resolve(__dirname), '../lib');
  var outputFile = pathMod.join(outputDir, namespacePrefix + '_bundle.js');
  var closureBuilder =
      pathMod.join(closureDir, 'closure/bin/build/closurebuilder.py');
  var command = [
    'python',
    closureBuilder,
    '--root=' + root,
    '--root=' + closureDir,
    '--root=' + outputDir,
    '--output_mode=' + (args.debug ? 'script' : 'compiled'),
    '--namespace=' + namespace,
    '--compiler_jar=' + compilerPath,
    '--compiler_flags="--language_in=ECMASCRIPT5_STRICT"',
    '--output_file=' + outputFile
  ];
  exec(
      command.join(' '),
      { encoding: 'utf8' },
      function(error, stdout, stderr) {
        if (error != null) {
          throw error;
        }
        generatedFiles.forEach(function(file) {
          fsMod.unlinkSync(file);
        });
      });
}


text:
package consulo.csharp.lang.psi.impl.source;

import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import consulo.annotation.access.RequiredReadAction;
import consulo.annotation.access.RequiredWriteAction;
import consulo.csharp.ide.refactoring.CSharpRefactoringUtil;
import consulo.csharp.lang.psi.CSharpElementVisitor;
import consulo.csharp.lang.psi.CSharpIdentifier;
import consulo.csharp.lang.psi.impl.source.resolve.type.wrapper.CSharpTupleTypeDeclaration;
import consulo.dotnet.psi.DotNetExpression;
import consulo.dotnet.psi.DotNetNamedElement;
import consulo.util.collection.ArrayUtil;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * @author VISTALL
 * @since 26-Nov-16.
 */
public class CSharpTupleElementImpl extends CSharpElementImpl implements PsiNameIdentifierOwner, DotNetNamedElement
{
	public CSharpTupleElementImpl(@Nonnull IElementType elementType)
	{
		super(elementType);
	}

	@RequiredReadAction
	public int getPosition()
	{
		PsiElement parent = getParent();
		if(parent instanceof CSharpTupleExpressionImpl tupleExpression)
		{
			return ArrayUtil.indexOf(tupleExpression.getElements(), this);
		}
		return -1;
	}

	@RequiredReadAction
	@Override
	public String getName()
	{
		CSharpIdentifier element = findChildByClass(CSharpIdentifier.class);
		return element == null ? null : CSharpPsiUtilImpl.getNameWithoutAt(element.getValue());
	}

	@Nullable
	@RequiredReadAction
	public DotNetExpression getExpression()
	{
		return findChildByClass(DotNetExpression.class);
	}

	@Override
	public void accept(@Nonnull CSharpElementVisitor visitor)
	{
		visitor.visitTupleElement(this);
	}

	@RequiredReadAction
	@Override
	public int getTextOffset()
	{
		PsiElement nameIdentifier = getNameIdentifier();
		return nameIdentifier == null ? super.getTextOffset() : nameIdentifier.getTextOffset();
	}

	@RequiredReadAction
	@Nullable
	@Override
	public PsiElement getNameIdentifier()
	{
		return findChildByClass(CSharpIdentifier.class);
	}

	@RequiredWriteAction
	@Override
	public PsiElement setName(@Nonnull String s) throws IncorrectOperationException
	{
		CSharpRefactoringUtil.replaceNameIdentifier(this, s);
		return this;
	}

	@Override
	public boolean isEquivalentTo(PsiElement another)
	{
		PsiElement tupleElement = another.getOriginalElement().getUserData(CSharpTupleTypeDeclaration.TUPLE_ELEMENT);
		if(tupleElement != null && super.isEquivalentTo(tupleElement))
		{
			return true;
		}
		return super.isEquivalentTo(another);
	}
}


text:
ACCEPTED

#### According to
International Plant Names Index

#### Published in
null

#### Original name
Opuntia subterranea R.Fries

### Remarks
null


text:
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    dependencies = [
        ('website', '0015_auto_20160418_1020'),
    ]

    operations = [
        migrations.AddField(
            model_name='tag',
            name='repository',
            field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='website.Repository'),
        ),
    ]


text:
<?php

namespace Doctrine\Tests\ORM\Functional\Locking;

use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Common\EventManager;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\Tests\TestUtil;

require_once __DIR__ . '/../../../TestInit.php';

class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
    protected function setUp()
    {
        parent::setUp();

        try {
            $this->_schemaTool->createSchema(array(
                $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedParent'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedChild'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticTimestamp')
            ));
        } catch (\Exception $e) {
            // Swallow all exceptions. We do not test the schema tool here.
        }
        $this->_conn = $this->_em->getConnection();
    }

    public function testJoinedChildInsertSetsInitialVersionValue()
    {
        $test = new OptimisticJoinedChild();
        $test->name = 'child';
        $test->whatever = 'whatever';
        $this->_em->persist($test);
        $this->_em->flush();

        $this->assertEquals(1, $test->version);
    }

    /**
     * @expectedException Doctrine\ORM\OptimisticLockException
     */
    public function testJoinedChildFailureThrowsException()
    {
        $q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedChild t WHERE t.name = :name');
        $q->setParameter('name', 'child');
        $test = $q->getSingleResult();

        // Manually update/increment the version so we can try and save the same
        // $test and make sure the exception is thrown saying the record was
        // changed or updated since you read it
        $this->_conn->executeQuery('UPDATE optimistic_joined_parent SET version = ? WHERE id = ?', array(2, $test->id));

        // Now lets change a property and try and save it again
        $test->whatever = 'ok';
        $this->_em->flush();
    }

    public function testJoinedParentInsertSetsInitialVersionValue()
    {
        $test = new OptimisticJoinedParent();
        $test->name = 'parent';
        $this->_em->persist($test);
        $this->_em->flush();

        $this->assertEquals(1, $test->version);
    }

    /**
     * @expectedException Doctrine\ORM\OptimisticLockException
     */
    public function testJoinedParentFailureThrowsException()
    {
        $q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedParent t WHERE t.name = :name');
        $q->setParameter('name', 'parent');
        $test = $q->getSingleResult();

        // Manually update/increment the version so we can try and save the same
        // $test and make sure the exception is thrown saying the record was
        // changed or updated since you read it
        $this->_conn->executeQuery('UPDATE optimistic_joined_parent SET version = ? WHERE id = ?', array(2, $test->id));

        // Now lets change a property and try and save it again
        $test->name = 'WHATT???';
        $this->_em->flush();
    }

    public function testStandardInsertSetsInitialVersionValue()
    {
        $test = new OptimisticStandard();
        $test->name = 'test';
        $this->_em->persist($test);
        $this->_em->flush();

        $this->assertEquals(1, $test->getVersion());
    }

    /**
     * @expectedException Doctrine\ORM\OptimisticLockException
     */
    public function testStandardFailureThrowsException()
    {
        $q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard t WHERE t.name = :name');
        $q->setParameter('name', 'test');
        $test = $q->getSingleResult();

        // Manually update/increment the version so we can try and save the same
        // $test and make sure the exception is thrown saying the record was
        // changed or updated since you read it
        $this->_conn->executeQuery('UPDATE optimistic_standard SET version = ? WHERE id = ?', array(2, $test->id));

        // Now lets change a property and try and save it again
        $test->name = 'WHATT???';
        $this->_em->flush();
    }

    public function testOptimisticTimestampSetsDefaultValue()
    {
        $test = new OptimisticTimestamp();
        $test->name = 'Testing';
        $this->_em->persist($test);
        $this->_em->flush();

        $this->assertTrue(strtotime($test->version) > 0);
    }

    /**
     * @expectedException Doctrine\ORM\OptimisticLockException
     */
    public function testOptimisticTimestampFailureThrowsException()
    {
        $q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticTimestamp t WHERE t.name = :name');
        $q->setParameter('name', 'Testing');
        $test = $q->getSingleResult();

        $this->assertType('DateTime', $test->version);

        // Manually increment the version datetime column
        $format = $this->_em->getConnection()->getDatabasePlatform()->getDateTimeFormatString();
        $this->_conn->executeQuery('UPDATE optimistic_timestamp SET version = ? WHERE id = ?', array(date($format, strtotime($test->version->format($format)) + 3600), $test->id));

        // Try and update the record and it should throw an exception
        $test->name = 'Testing again';
        $this->_em->flush();
    }
}

/**
 * @Entity
 * @Table(name="optimistic_joined_parent")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"parent" = "OptimisticJoinedParent", "child" = "OptimisticJoinedChild"})
 */
class OptimisticJoinedParent
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    public $id;

    /**
     * @Column(type="string", length=255)
     */
    public $name;

    /**
     * @Version @Column(type="integer")
     */
    public $version;
}

/**
 * @Entity
 * @Table(name="optimistic_joined_child")
 */
class OptimisticJoinedChild extends OptimisticJoinedParent
{
    /**
     * @Column(type="string", length=255)
     */
    public $whatever;
}

/**
 * @Entity
 * @Table(name="optimistic_standard")
 */
class OptimisticStandard
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    public $id;

    /**
     * @Column(type="string", length=255)
     */
    public $name;

    /**
     * @Version @Column(type="integer")
     */
    private $version;

    function getVersion() {return $this->version;}
}

/**
 * @Entity
 * @Table(name="optimistic_timestamp")
 */
class OptimisticTimestamp
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    public $id;

    /**
     * @Column(type="string", length=255)
     */
    public $name;

    /**
     * @Version @Column(type="datetime")
     */
    public $version;
}


text:
.SelectArea-box{
    width: 100vw;
    height: 5rem;
    background-color: #ffffff;
    margin-bottom: 10px;

}
.SelectArea-box .SelectArea-cont{
  position: relative;
    overflow:scroll;
    height: 100%;
    width: 100%;
}
.SelectArea-box .SelectArea-cont i{
  position: absolute;
  width: 40px;
  height: 3px;
  border-radius: 3px;
  background-color: #23b3ff;
  bottom: 8%;
  left: 25px;
}
.SelectArea-box .SelectArea-cont ul{
  height: 100%;
  width: 880px;
  margin: 0;
  padding: 0;
}
.SelectArea-box .SelectArea-cont ul li{
  width: 80px;
  height: 100%;
  padding: 10px;
  display: inline-block;
  box-sizing: border-box;
  position: relative;
}
.SelectArea-box .SelectArea-cont ul li div{
  height: 100%;
  width: 60px;
  display: inline-flex;
  display: -webkit-inline-flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5rem;

}
.SelectArea-box .SelectArea-cont ul li i{

}


text:
layout: page
title: Jewish Studies
comments: true
description: "blank"
keywords: JWST, CU, Boulder
---

JWST 1234: Mystics And Messiahs: The Jewish Tradition

JWST 1818: Introduction To Jewish History: Bible To 1492

JWST 2350: Introduction To Jewish Culture

JWST 2551: Jewish Literature:  Jews Coming Of Age

JWST 2600: Judaism, Christianity, And Islam

JWST 3202: Women, Gender & Sexuality In Jewish Texts & Traditions

JWST 3600: Global Secular Jewish Societies

JWST 4050: Anthropology Of Jews And Judaism

JWST 4101: Topics In Hebrew Studies

JWST 4203: Israeli Literature: Exile, Nation, Home

JWST 4827: Modern U.S. Jewish History


text:
using Eth.Rpc;
using Newtonsoft.Json;
using System;

namespace Eth.Json.Converters
{
    public class FunctionInputOutputConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(FunctionInputOutput);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
        {
            FunctionInputOutput functionInputOutput = new FunctionInputOutput();
            int startingDepth = reader.Depth;

            while (!(reader.TokenType == JsonToken.EndObject && reader.Depth == startingDepth))
            {
                reader.Read();
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    string propertyName = reader.Value.ToString();

                    if (String.Equals(propertyName, "name"))
                    {
                        reader.Read();
                        functionInputOutput.Name = reader.Value.ToString();
                    }
                    else if (String.Equals(propertyName, "type"))
                    {
                        reader.Read();
                        functionInputOutput.Type = reader.Value.ToString();
                    }
                }
            }

            return functionInputOutput;
        }

        public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override bool CanWrite { get { return false; } }
    }
}


text:
authors: Andrew Lytvynov (andrew@goteleport.com)
state: draft
---

# RFD 34 - Desktop Access - Windows

## What

RFD 33 defines the high-level goals and architecture for Teleport Desktop
Access.

This RFD specifies how Teleport Desktop Access integrates with Windows hosts,
including Microsoft Active Directory domains.

## Details

### Architecture

Windows Desktop Access is implemented using `windows_desktop_service` that
translates the Teleport desktop protocol into RDP:

```
+--------+
| web UI |
+--------+
    ^
    | desktop protocol over websocket
    v
+--------+
| proxy  |
+--------+
    ^
    | desktop protocol over mTLS
    v
+-------------------------+
| windows_desktop_service |--------------\
+-------------------------+-\            |
   ^                        |            |
   | RDP                    | RDP        | LDAP
   v                        v            |
+---------------------+  +-----------+  +-------------------+
| windows server 2012 |  | windows 7 |  | domain controller |
+---------------------+  +-----------+  +-------------------+
```

`windows_desktop_service` can talk to any number of remote Windows RDP hosts.
It can also talk to `localhost` RDP service, if installed on a Windows machine
in agent mode (described below).

`windows_desktop_service` has the ability to automatically discover available
Windows hosts from Active Directory by performing an LDAP search. In addition,
`windows_desktop_service` can use a static list of Windows hosts provided in
`teleport.yaml`.

### Supported versions

Windows Desktop Access supports Windows Server 2012 R2, Windows 7 and newer
versions. However, it should also work with any server that implements RDP and
supports Smart Card authentication.

### Protocol

Windows Desktop Access uses Remote Desktop Protocol (RDP). RDP service is built
into Windows and requires no additional software to be installed on the hosts.

RDP is a very complex protocol, with cruft accumulated over its long history
and frequent vulnerability discoveries (see [Security
Concerns](#security-concerns) below). It was not my first choice for this
implementation. However, it is the only option for supporting concurrent
sessions and allows easier customer rollout without per-host agents.

#### RDP client

`windows_desktop_service` implements an RDP client. There are no existing Go
libraries implementing enough of the RDP spec for a basic desktop session.

There are a few options, in order of preference:
- use [rdp-rs Rust library](https://crates.io/crates/rdp-rs) via FFI from Go,
  assuming it supports smart cards
- use [libfreerdp](https://www.freerdp.com/) via CGO, assuming it supports
  smart cards and concurrent outbound connections
- implement RDP protocol in Go from scratch; last resort due to the amount of
  work needed

### Modes

`windows_desktop_service` can run in two modes: gateway and agent.

#### Gateway mode

Gateway mode is for connecting to multiple remote Windows hosts, similar to
Kubernetes Access. This mode is shown in the [Architecture
diagram](#architecture) above.

This mode is easy for admins to set up and has minimal resource overhead.
However, this requires the Windows hosts to expose RDP ports to the
`windows_desktop_service`, which is more risky (see [Security
Concerns](#security-concerns) below).

#### Agent mode

Agent mode is for running a `windows_desktop_service` instance on the Windows
host as a system service. In this mode, connection is made over `localhost` and
the RDP port does not need to be exposed on the network.
`windows_desktop_service` can reverse-tunnel to the Teleport proxy, allowing
the Windows host to completely block all inbound connections. In the future,
`windows_desktop_service` could also collect more session information (like
eBPF on Linux) and enforce extra restrictions.

```
+--------+
| web UI |
+--------+
    ^
    | desktop protocol over websocket
    v
+--------+
| proxy  |
+--------+
    ^
    | desktop protocol over mTLS over reverse tunnel
    |
+---|------------------------------+
|   v                              |
| +-------------------------+      |
| | windows_desktop_service |      |
| +-------------------------+      |
|   ^                              |
|   | RDP over localhost           |
|   v                              |
| +-------------+                  |
| | RDP service |                  |
| +-------------+     Windows host |
+----------------------------------+
```

### Authentication

In Windows, authentication is handled differently for standalone and
Active Directory-enrolled machines. Standalone machines validate credentials
using the local user database (SAM). Active Directory-enrolled machines send
credentials to the domain controller for validation. Teleport Desktop Access
will support both modes.

Windows generally exposes 3 authentication mechanisms:
- smart cards
- username/password
- kerberos tickets

#### Smart cards

Smart cards implement asymmetric cert-based authn, using PKI configured on the
server/AD side. Since this is the only known way for us to support cert-based
authn, Teleport will implement a smart card emulator to authenticate over RDP.
This will be the primary authentication method.

Smart card authentication and emulator are described in more detail in RFD 35.

#### Username/password

Although username and password are the most universal, a major part of
Teleport's value is to provide strong autentication using short-lived
certificates. Supporting username and password authentication would weaken the
overall security of the system and as such will not be implemented.

#### Kerberos tickets

When a user is already authenticated against Kerberos (using one of the above
methods), they get a Ticket-granting ticket (TGT) which can be used to get
other tickets for specific services, such as an RDP host. Since Teleport has no
exposure to Kerberos tickets (even when using AAD as SSO provider) and we can't
assume that all clients use Windows machines, Teleport will not use TGTs for
RDP authentication.

### Host discovery

When a user starts a new desktop session, they must specify the Windows host to
connect to. Internally, Teleport tracks known Windows hosts using
`WindowsDesktop` objects.

There are 3 ways that `windows_desktop_service` discovers Windows hosts to
register:
- hardcoded list of hosts provided in the config file (see
  [configuration](#configuration))
- list of Active Directory-enrolled hosts obtained from AD via LDAPS (LDAP over
  SSL)
  - LDAP library: https://pkg.go.dev/github.com/go-ldap/ldap/v3
- local host, when running on a Windows machine in agent mode

By default, Teleport will only register hosts that are provided in the
configuration file. To enable host discovery over LDAP, additional configuration
is necessary (see [configuration](#configuration)).

#### Automatic Host Labels

Teleport will automatically apply the following host labels to hosts which are
discovered from Active Directory.

| Label | LDAP Attribute | Example |
| ----- | -------------- | ------- |
| `teleport.dev/computer_name` | `name` | `WIN-I5G06B8RT33`
| `teleport.dev/dns_host_name` | [`dNSHostName`](https://docs.microsoft.com/en-us/windows/win32/adschema/a-dnshostname) | `WIN-I5G06B8RT33.example.com`
| `teleport.dev/os` | [`operatingSystem`](https://docs.microsoft.com/en-us/windows/win32/adschema/a-operatingsystem) | `Windows Server 2012`
| `teleport.dev/os_version`| [`osVersion`](https://docs.microsoft.com/en-us/windows/win32/adschema/a-operatingsystemversion) | `4.0`
| `teleport.dev/windows_domain`| Sourced from config | `example.com`

### Concurrent sessions

RDP supports concurrent user sessions on the same host. It allocates a virtual
desktop for each user to isolate their activities. However, it only allows a
single session per user per host. If a user starts a new session on the host
that they are already logged into, they will log out the other session. This is
RDP behavior we cannot change.

All the usual controls on Teleport sessions apply to Desktop Access, like user
locking, concurrent session limits and idle timeouts.

### Configuration

New `teleport.yaml` section for `windows_desktop_service`:

```yaml
windows_desktop_service:
  enabled: yes # default false
  # listen_addr can share the port with the proxy web port using SNI.
  listen_addr: 0.0.0.0:3080
  public_addr: [rdp.example.com:3080]
  mode: "gateway" # or "agent"
  # (optional) ldap contains hostname and credentials for the LDAP server on
  # the Active Directory domain controller.
  # If specified, windows hosts will be automatically discovered by Teleport.
  #
  # Note: Teleport will only connect to LDAP over TLS and will always
  # validate the server certificate.
  ldap:
    host: ldap.example.com
    username: "ldap_user"
    password: "ldap_pass"
    # optional CA cert to use for LDAP server certificate validation.
    ca_cert: "/var/lib/teleport/ldap_ca.pem"
  # (optional) hosts is a list of hostnames to register as WindowsDesktop
  # objects in Teleport.
  # These are usually non-AD hosts.
  hosts:
  - win1.example.com
  - win2.example.com
  - ...
  # (optional) settings for enabling automatic desktop discovery via LDAP
  discovery:
    base_dn: '*' # wildcard searches from the root, leave empty to disable discovery
    filters:  # additional LDAP filters: https://ldap.com/ldap-filters/
    - filter1 # note: multiple filters are combined into an AND filter
    - filter2
  # (optional) host_labels applies labels to windows hosts for RBAC.
  # Each entry maps to a subset of hosts by regexp and applies a group of labels.
  # A host can match multiple regexps and will get a union of all the labels.
  # The regexp is matched against the host's DNS name, for example:
  # WIN-I5G06B8RT33.example.com (where example.com is the domain name)
  host_labels:
  - match: ".*"
    labels:
      env: prod
  - match: "^db.*"
    labels:
      type: database
      kind: postgres
  - match: "^dc\.example\.com$"
    labels:
      type: domain_controller
```

### Security concerns

RDP is a very complex protocol with a history of vulnerabilities. Using a
memory-safe client that we fully control and not exposing raw RDP publicly is
essential. Running Teleport in agent mode is and extra hardening step to avoid
exposing RDP even on private networks.

Generally, admins are still responsible for patching their Windows hosts to
pick up any RDP server fixes that come out.

The RDP client implementation in Teleport should be reasonably paranoid, verify
the identity of the target RDP host and treat it as potentially malicious.


text:
class Browser;
class PrefService;

namespace content {
class WebContents;
}

// BookmarkPromptController is a kind of singleton object held by
// BrowserProcessImpl, and controls showing bookmark prompt for frequently
// visited URLs.
class BookmarkPromptController : public chrome::BrowserListObserver,
                                 public content::NotificationObserver,
                                 public TabStripModelObserver {
 public:
  // When impression count is greater than |kMaxPromptImpressionCount|, we
  // don't display bookmark prompt anymore.
  static const int kMaxPromptImpressionCount;

  // When user visited the URL 10 times, we show the bookmark prompt.
  static const int kVisitCountForPermanentTrigger;

  // When user visited the URL 3 times last 24 hours, we show the bookmark
  // prompt.
  static const int kVisitCountForSessionTrigger;

  // An instance of BookmarkPromptController is constructed only if bookmark
  // feature enabled.
  BookmarkPromptController();
  virtual ~BookmarkPromptController();

  // Invoked when bookmark is added for |url| by clicking star icon in
  // |browser|. Note: Clicking bookmark menu item in action box is also
  // considered as clicking star icon.
  static void AddedBookmark(Browser* browser, const GURL& url);

  // Invoked when bookmark prompt is closing.
  static void ClosingBookmarkPrompt();

  // Disable bookmark prompt feature in a profile in |prefs|.
  static void DisableBookmarkPrompt(PrefService* prefs);

  // True if bookmark prompt feature is enabled, otherwise false.
  static bool IsEnabled();

 private:
  // TabStripModelObserver
  virtual void ActiveTabChanged(content::WebContents* old_contents,
                                content::WebContents* new_contents,
                                int index,
                                int reason) OVERRIDE;

  void AddedBookmarkInternal(Browser* browser, const GURL& url);
  void ClosingBookmarkPromptInternal();

   // content::NotificationObserver:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // chrome::BrowserListObserver
  virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
  virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;

  // Callback for the HistoryService::QueryURL
  void OnDidQueryURL(CancelableRequestProvider::Handle handle,
                     bool success,
                     const history::URLRow* url_row,
                     history::VisitVector* visits);

  // Set current active browser cache to |browser|. |browser| can be null.
  void SetBrowser(Browser* browser);

  // Set current active WebContents cache from |web_contents|. |web_contents|
  // can be null.
  void SetWebContents(content::WebContents* web_contents);

  // Current active browser cache which we will display the prompt on it.
  Browser* browser_;

  // Current active WebContents cache which we will display the prompt for it.
  content::WebContents* web_contents_;

  // Remember last URL for recording metrics.
  GURL last_prompted_url_;

  // Last prompted time is used for measuring duration of prompt displaying
  // time.
  base::Time last_prompted_time_;

  // Start time of HistoryService::QueryURL.
  base::Time query_url_start_time_;

  CancelableRequestConsumer query_url_consumer_;
  content::NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkPromptController);
};

#endif  // CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_PROMPT_CONTROLLER_H_


text:
import loadFont from './loadFont.js'

loadFont([
	{ family: 'Benton', suffix: 'bold', weight: 600 },
	{ family: 'Miller', suffix: 'regular', weight: 400 },
	{ family: 'Benton', suffix: 'regular', weight: 400 },
])