Nueva publicación

Encontrar

Artículo
· 16 jul, 2024 Lectura de 9 min

管理ポータルのウェブ・アプリケーションメニューの設定をプログラムで作成する方法

これは InterSystems FAQ サイトの記事です。

管理ポータル > [システム管理] > [セキュリティ] 以下の設定は、%SYSネームスペースにあるSecurityパッケージ以下クラスが提供するメソッドを利用することでプログラムから作成することができます。

以下シナリオに合わせたセキュリティ設定例をご紹介します。

シナリオ:RESTアプリケーション用設定を作成する

事前準備

シナリオの中で使用するソースを2種類インポートします。

アプリケーション用RESTディスパッチクラスをインポートします。

Class Test.REST Extends %CSP.REST
{

Parameter CHARSET = "utf-8";
Parameter CONTENTTYPE = "application/json";
Parameter CONVERTINPUTSTREAM = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/hello" Method="POST" Call="TestInsert" Cors="true" />
<Route Url="/hello" Method="DELETE" Call="TestDelete" Cors="true" />
</Routes>
}

/// Description
ClassMethod TestInsert() As %Status
{
    #dim %request As %CSP.Request
    #dim rset As %SQL.StatementResult
    set status = $$$OK
    Try {
        set bodyjson={}.%FromJSON(%request.Content)
        set ^Test=bodyjson.Message
        set stmt=##class(%SQL.Statement).%New()
        $$$ThrowOnError(stmt.%Prepare("insert into Test.Human (Name,Message) VALUES(?,?)"))
        set rset=stmt.%Execute($username,bodyjson.Message)
        if rset.%SQLCODE<0 {
            throw ##class(%Exception.SQL).CreateFromSQLCODE(rset.%SQLCODE,rset.%Message)
        }
        set j={}
        set j.Result="こんにちは!メッセージをUSERネームスペースのグローバル^TestとTest.Humanテーブルに格納しました。"
        do j.%ToJSON()     }
    Catch ex {
        Set status=ex.AsStatus()
    }
    Return status
}

ClassMethod TestDelete() As %Status
{
    #dim %request As %CSP.Request
    #dim rset As %SQL.StatementResult
    set status = $$$OK
    Try{
        kill ^Test
        set stmt=##class(%SQL.Statement).%New()
        $$$ThrowOnError(stmt.%Prepare("Delete from Test.Human"))
        set rset=stmt.%Execute()
        if rset.%SQLCODE<0 {
            throw ##class(%Exception.SQL).CreateFromSQLCODE(rset.%SQLCODE,rset.%Message)
        }
        set j={}
        set j.Result="USERネームスペースの^TestとTest.Humnaのデータを削除しました"
        do j.%ToJSON()
    }
    catch ex {
        Set status=ex.AsStatus()
    }
    Return status
}

}

続いて、Test.Humanテーブル用定義もインポートします。

Class Test.Human Extends %Persistent
{

Property Name As %String;
Property Message As %String;
}

 

それでは設定してみましょう。

1) RESTアプリケーション(/testApp)があり、USERネームスペースで動作するRESTアプリケーションに対して不特定多数のユーザが利用できるようにします=(認証なしアクセスを許可します)。

2) RESTアプリケーション利用時は、USERネームスペースのTestスキーマ以下テーブルに対してINSERT/UPDATE/DELETE/SELECTが行えるように設定します。

 

まずは 1)について、

認証をしない「認証なし」アクセスを許可した場合、UnknownUserとしてInterSystems製品にログインします。

UnknownUserはインストール時の初期セキュリティの指定により初期設定が異なります。(初期セキュリティについて詳細は、記事「インストール時の初期セキュリティについて」をご参照ください。)

  • 「最小」:InterSystems製品の全ての情報にアクセス可能な %Allロールが付与されます。
  • 「通常」以上を指定した場合:ロールは何も設定されません。

このシナリオでは、UnkownUserに対してロールが付与されていない環境(=インストール時の初期セキュリティを「通常」以上とした場合)に対する設定方法を解説します。

手っ取り早くUnkownUserに%Allロールを付与するのも1つの方法ですが、その場合RESTアプリケーション以外の「認証なし」が許可されたアクセスに対しても%Allロールが適用されてしまうため、セキュアな設定とは言えません。このシナリオでは、RESTアプリケーションパスを通過したときのみ適切なロールを付与させることのできる「アプリケーションロール」を利用してロールを付与していきます。

ここで、RESTアプリケーションを動作させるために最低限必要となるアクセス許可はアプリケーションが動作するデータベースに対するREAD許可です。アプリケーションがデータベースに対して書き込みを行う場合はWRITE許可も必要となります。

InterSystems製品では、データベースを作成した際、一緒にセキュリティ設定で使用するデータベースリソースを作成することができます。データベースリソースを作成するとそのリソースに対するREADとWRITEの許可を持ったデータベースロールが自動的に作成されます。

今回はインストールデフォルトで作成されるUSERデータベースにアプリケーションをインストールして利用することにしています。

USERデータベースに対しては、%DB_USERリソースが用意されていてこのリソースに対してREADとWRITE許可を持つ%DB_USERロールが事前に用意されています。この%DB_USERロールをRESTアプリケーションに付与することにします。

 

さらに、2)では、

2) RESTアプリケーション利用時は、USERネームスペースのTestスキーマ以下テーブルに対してINSERT/UPDATE/DELETE/SELECTが行えるように設定します。

とあるので、Testスキーマに対する適切なテーブル権限が必要となります。テーブル権限はユーザに直接付与することもロールに付与することもできます。

この設定では、RESTアプリケーションにロールを付与したいので、ロールにテーブルの権限も付与することにします。

それでは、ロール:MyAppRoleを作成します。

アプリケーションはUSERネームスペースにアクセスする前提のため、%DB_USERロールを持つ新ロールを作成します。

%SYSネームスペースで実行します。

set $namespace="%SYS"
set status=##class(Security.Roles).Create("MyAppRole","アプリケーション用ロール",,"%DB_USER")

Security.RolesクラスCreate()メソッドに指定する引数は以下の通りです。

第1引数:ロール名
第2引数:ロールの説明
第3引数:リソースの割り当て(未指定もOK)
第4引数:割り当てるロール(複数ある場合はカンマ区切りで指定)

このロールを付与された人やアプリケーションはTestスキーマに対してSELECT/DELETE/UPDATE/INSERTができるようにこれらの権限を含む全テーブル権限を追加します。

set status=$system.SQL.Security.GrantPrivilege("*","Test","SCHEMA","MyAppRole")

%SYSTEM.SQL.SecurityクラスGrantPrivilege()メソッドで指定する引数は以下の通りです。

第1引数:以下のアクションをカンマ区切りで指定します。全部対象とする場合は * を指定します。

  • Alter
  • Select
  • Insert
  • Update
  • Delete
  • References
  • Execute
  • Use

第2引数:対象となるテーブル名やスキーマ名を指定できます。例ではTestスキーマを指定しています。

第3引数:対象となるタイプを指定します。例ではSCHEMAを指定しています。

第4引数:付与するユーザ名またはロール名を指定します。

戻り値を確認します。(1が返れば成功です。)

失敗している場合は、以下の出力をご確認ください。

do $system.OBJ.DisplayError(status)

管理ポータルでは以下のように設定を確認できます。

管理ポータル > [システム管理] > [セキュリティ] > [ロール] > [MyAppRole]の[Assigned To]と[SQL Tables]のタブ

 

作成したMyAppRoleをアプリケーション利用時に追加するようにREST用のウェブアプリケーションを定義します。

作成には、Security.ApplicationsクラスCreate()メソッドを利用します。

Create()メソッドの第2引数には設定に必要な情報を配列変数で指定します。サブスクリプトの指定については以下の通りです。

  • DispatchClass:RESTディスパッチクラス名を指定します。
  • NameSpace:RESTディスパッチクラスがあるネームスペースを指定します。
  • Enable:アプリケーションを有効とする場合は1を指定します。
  • AutheEnabled:認証なしは64を設定します。詳細はAutheEnabledプロパティの説明をご参照ください。(認証なしは Bit 6のAutheUnauthenticated の値を設定します。)
  • MatchRoles:アプリケーション通過時に付与するアプリケーションロールの場合は、:ロール名 を設定します。

%SYSネームスペースで以下実行します。 

set webName="/testApp"
set webProperties("DispatchClass")="Test.REST"
set webProperties("NameSpace")="USER"
set webProperties("Enable")=1
set webProperties("AutheEnabled")=64
set webProperties("MatchRoles")=":MyAppRole"
set status=##class(Security.Applications).Create(webName, .webProperties)

戻り値を確認します。(1が返れば成功です。)

失敗している場合は、以下の出力をご確認ください。

do $system.OBJ.DisplayError(status)

管理ポータルでは以下のように表示されます。

管理ポータル > [システム管理] > [セキュリティ] > [アプリケーション] > [ウェブ・アプリケーション] > /testApp選択

 

設定が完了したので最初にPOST要求を試します。 URLには、webサーバ/testApp/hello を指定しBodyに以下のプロパティを持つJSONを指定しPOST要求をテストします。

{
    "Message":"新しいデータをいれます"
}

 POST要求が成功すると、以下応答として返送します。

{
    "Result": "こんにちは!メッセージをUSERネームスペースのグローバル^TestとTest.Humanテーブルに格納しました。"
}

グローバル^Test、またはTest.Humanの中身をご確認ください。

 

続いて、DELETE要求を実行します。(POSTと同じURLを使用します)

 DELETE要求が成功すると、以下応答として返送します。

{
    "Result": "USERネームスペースの^TestとTest.Humnaのデータを削除しました"
}

グローバル^TestとTest.Humanテーブルのデータが削除されたことを確認してください。

 

ご参考:RESTアプリケーション(/testApp)にテーブル権限を設定し忘れると以下のエラーが出力されます。

{
    "errors": [
        {
            "code": 5540,
            "domain": "%ObjectErrors",
            "error": "エラー #5540: SQLCODE: -99 メッセージ: User UnknownUser is not privileged for the operation",
            "id": "SQLCode",
            "params": [
                -99,
                "User UnknownUser is not privileged for the operation"
            ]
        }
    ],
    "summary": "エラー #5540: SQLCODE: -99 メッセージ: User UnknownUser is not privileged for the operation"
}
Comentarios (0)1
Inicie sesión o regístrese para continuar
Pregunta
· 16 jul, 2024

The issue of Concurrent External Backup

After performing Concurrent External Backup and restarting the instance, if I want to perform an incremental backup of Concurrent External Backup again.

Should I redo the following steps?

  1.  Do CLRINC^DBACK("QUIET")
  2.  Set x=$$BACKUP^DBACK("","E","Dirty external backup - incrementals must be applied.","","","")
  3. Set x=$$BACKUP^DBACK("","I","Nightly","test.bck","N","bck.log","QUIET","N","Y")
1 Comentario
Comentarios (1)2
Inicie sesión o regístrese para continuar
Pregunta
· 16 jul, 2024

Add Zen component

Hi Guy,

I'm currently using a classmethod to load my page's display content in a form of html want look good, I'm wondering if I can add a Zen component in my classmethod eg. <dataCombo> or Label...etc

I've tried the bit of code (circled in red) but didn't work 

 

Thanks

4 comentarios
Comentarios (4)2
Inicie sesión o regístrese para continuar
Artículo
· 16 jul, 2024 Lectura de 2 min

プログラムでSQLゲートウェイ接続設定を作成する方法

これは InterSystems FAQ サイトの記事です。
 

SQLゲートウェイの接続設定は管理ポータルで作成できますが、プログラムでも作成が可能です。

管理ポータル:
[システム管理] > [構成] > [接続性] > [SQLゲートウェイ接続]

こちらのトピックでは、ODBC/JDBCそれぞれの設定をプログラムで行う方法をご紹介します。


--- SQL Gateway for ODBC ----

 set gc = ##class(%SQLConnection).%New()
 set gc.Name = "test"
 set gc.DSN = "IRIS User"
 set gc.Usr = "_system"
 set gc.pwd = "SYS"
 set gc.bUnicodeStream = 1
 set gc.useCOALESCE = 1
 write gc.%Save()
 


--- SQL Gateway for JDBC ----

 set gc = ##class(%SQLConnection).%New()
 set gc.isJDBC = 1
 set gc.Name = "testj"
 set gc.Usr = "_system"
 set gc.pwd = "SYS"
 set gc.driver = "com.intersystems.jdbc.IRISDriver"
 set gc.URL = "jdbc:IRIS://127.0.0.1:1972/User"
 set gc.classpath = "C:\InterSystems\IRIS\dev\java\lib\1.8\intersystems-jdbc-3.7.1.jar"
 set gc.useCOALESCE = 1
 write gc.%Save()


 

接続テストは以下のように行います。

--- SQL Gateway Connection Test for ODBC ----

USER>d $system.SQLGateway.TestConnection("test")
 
Connection successful


--- SQL Gateway Connection Test for JDBC ----

USER>d $system.SQLGateway.TestConnection("testj")
 
Connection successful



enlightened【ご参考】
SQL ゲートウェイを使用した外部データベースへのアクセス方法について
(管理ポータルで行う)リンクテーブルをプログラムで行う方法
 

Comentarios (0)0
Inicie sesión o regístrese para continuar
Artículo
· 16 jul, 2024 Lectura de 2 min

Configuração de VSCode Auto Save e ObjectScript CompileOnSave

Olá!

Recentemente estive investigando uma situação incômoda enquanto editava classes ou rotinas ObjectScript no VSCode. O que acontecia era que, como estava escrevendo as linhas de código na minha classe (por exemplo: a adição de um novo método, mudança da assinatura de classe ou de um bloco de código) isso ocasionava uma rápida revisão da sintaxe, reformatação e compilação - e inevitavelmente (já que eu estava apenas na metade da escrita), isso gerava erros de compilação.

Sabendo que estava a meio caminho de adicionar código, podia simplesmente descartar essa mensagem, mas isso começou a ficar incômodo e me condicionou a ignorar possíveis erros (o que não é bom).

Ainda pior, o processo de compilação também reformatava o documento e às vezes rompia o que antes eram linhas de código bem formatadas (que apareciam abaixo da linha que eu estava escrevendo, o que me obrigava a ir até essa zona do documento e arrumá-las novamente.

O que é isso que acontece?

Há duas configurações em jogo:

  1. A configuração de salvar automaticamente do VSCode (files.autosave), que dita se deve salvar automaticamente um documento que tenha sido modificado e, se sim, quanto tempo esperar antes de salvar (files.autoSaveDelay)
  2. CompileOnSave da extensão ObjectScript (objectscript.compileOnSave), que determina se depois de salvar o documento, ele também se importa e compila no namespace conectado do IRIS.

Como eu tinha o autosave ativado, e com um retardo de espera pequeno, junto com o compileOnSave, significava que o código parcialmente editada se seguia compilando, gerando os erros aos quais me referi, e como mencionado, às vezes reformatando blocos de códigos bons pré-existentes.

No meu caso, decidi pelo seguinte:

  1. Autosalvar (files.autosave) desativado (se ignora autosaveDelay), e...
  2. CompileOnSave (objectscript.compileOnSave) ativado.

Agora, quando estou satisfeito com minhas edições (e quando eu queira!), aperto Ctrl+S para salvar, importar e compilar minha classe, e estou atento a essa mensagem emergente que agora tem verdadeiro significado e propósito.

Você pode escolher uma combinação diferente (por exemplo, seguir em frente e salvar automaticamente depois de 5 minutos mais ou menos, aceitando que o código pode não compilar completamente). No entanto, decidi que a combinação anterior funciona para mim, e espero que - se você está passando pelo mesmo incômodo, esse artigo possa ajudá-lo a encontrar sua configuração ótima.

Agradeço a @Patrick Sulin, e @Raj Singh por me indicar como chegar a estes ajustes!

Comentarios (0)1
Inicie sesión o regístrese para continuar