Skip to content

Commit 9b4f4d0

Browse files
authored
Merge pull request #232 from piql/release/v1.0
Publish official release of PiqlConnect v1.0
2 parents 25c5447 + 6c5e0ef commit 9b4f4d0

File tree

319 files changed

+34379
-21719
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

319 files changed

+34379
-21719
lines changed

.env.example

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ APP_URL=http://_HOSTNAME_
1818
# sent with bags
1919
#APP_AM_INGEST_METADATA_FILE_FORMAT=csv
2020

21-
# APP_INGEST_BUCKET_SIZE (default = 115000000000)
21+
# APP_INGEST_BUCKET_SIZE (default = 120000000000)
2222
# After a complete ingest AIPs are added to a bucket
2323
# Sets the maximum bucket size in bytes
24-
#APP_INGEST_BUCKET_SIZE=115000000000
24+
#APP_INGEST_BUCKET_SIZE=120000000000
2525

2626
# Ingest validation service (default = App\Services\IngestValidationService)
2727
#APP_INGEST_VALIDATION_SERVICE=App\Services\IngestValidationService
@@ -31,9 +31,22 @@ APP_URL=http://_HOSTNAME_
3131

3232
# Uploder path
3333
STORAGE_UPLOADER_PATH=uploader
34+
3435
# Bag path
3536
STORAGE_BAGS_PATH=bags
3637

38+
# Job path
39+
STORAGE_JOBS_PATH=jobs
40+
41+
# Messages processing path
42+
STORAGE_MESSAGES_PROCESSING_PATH=messages-processing
43+
44+
# Messages processed path
45+
STORAGE_MESSAGES_PROCESSED_PATH=messages-processed
46+
47+
# Messages failed path
48+
STORAGE_MESSAGES_FAILED_PATH=messages-failed
49+
3750
# Archivematica transfer path
3851
# This is where ingested bags are stored
3952
STORAGE_TRANSFER_PATH=am/ss-location-data
@@ -120,3 +133,14 @@ MONGO_DB_PORT=27017
120133
MONGO_DB_DATABASE=connectstats
121134
MONGO_DB_USERNAME=connectuser
122135
MONGO_DB_PASSWORD=Fw86TQZrJ5
136+
137+
PIQLIT_NOTIFY_EMAIL_TO=
138+
139+
# Authentication service base url
140+
APP_AUTH_SERVICE_BASE_URL=https://auth.piqlconnect.com
141+
# Authentication service realm
142+
APP_AUTH_SERVICE_REALM=development
143+
# Callback service client
144+
APP_AUTH_SERVICE_CALLBACK_CLIENT=piql-service-callback
145+
# Callback service client secret
146+
APP_AUTH_SERVICE_CALLBACK_CLIENT_SECRET=65b244cc-7a91-42cb-b997-5c22e7a3daa0

.env.testing.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ CURL_VERIFY_SELF_SIGN_CERT=true
1111

1212
STORAGE_UPLOADER_PATH=uploader
1313
STORAGE_BAGS_PATH=bags
14+
STORAGE_JOBS_PATH=jobs
15+
STORAGE_MESSAGES_PROCESSING_PATH=messages-processing
16+
STORAGE_MESSAGES_PROCESSED_PATH=messages-processed
17+
STORAGE_MESSAGES_FAILED_PATH=messages-failed
1418
STORAGE_TRANSFER_PATH=am/ss-location-data
1519
STORAGE_LOCATION_ID=3bf2fd97-5350-4ace-a4dc-02045ae97076
1620

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,9 @@ package-lock.json
4848
*.js.snap
4949

5050
.composer
51-
composer.phar
51+
composer.phar
52+
.rnd
53+
piql_connect.code-workspace
54+
resources/js/app.jse
55+
56+
.vscode/settings.json

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,30 @@ $ npm run dev
8282

8383
To get piqlConnect rebuilt from your local shell.
8484

85+
### End-to-end tests
86+
87+
To perform user interface tests, you must run:
88+
89+
```
90+
$ cd tests/endToEnd/
91+
$ ./ui-test.sh
92+
93+
```
94+
95+
It will open a background Chrome browser and navigate thoward some key actions in piqlConnect.
96+
97+
All the actions happens inside "selenium/standalone-chrome" docker image.
98+
99+
However it's possible to se theese actions if you change the image to a debug version.
100+
101+
Edit "deploy/docker-compose.yml" file and append "-debug" to "selenium/standalone-chrome-chrome" image name:
102+
103+
```
104+
selenium-chrome:
105+
image: selenium/standalone-chrome-chrome-debug
106+
107+
```
108+
109+
Stop the previous container and start the new one.
110+
111+
Now you wil be able to use VNC at 5900 port and see Chrome running. Use VNC password "secret".

app/Account.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Str;
7+
use Webpatser\Uuid\Uuid;
8+
use Illuminate\Support\Facades\Validator;
9+
10+
class Account extends Model
11+
{
12+
const DEFAULT_TEMPLATE = '{ "title": "", "description": "", "dc": { "identifier": "" } }';
13+
14+
/**
15+
* The attributes that are mass assignable.
16+
*
17+
* @var array
18+
*/
19+
protected $fillable = [
20+
'uuid',
21+
'title',
22+
'description',
23+
'defaultMetadataTemplate'
24+
];
25+
26+
protected $attributes = [
27+
'defaultMetadataTemplate' => self::DEFAULT_TEMPLATE
28+
];
29+
30+
31+
protected $casts = [
32+
'defaultMetadataTemplate' => 'array'
33+
];
34+
35+
protected static function boot()
36+
{
37+
parent::boot();
38+
39+
static::creating( function ( $model ) {
40+
$validateIdentifier = Validator::make( ['uuid' => $model->uuid], ['uuid' => 'uuid'] );
41+
if( !$validateIdentifier->passes() ){
42+
$model->uuid = Str::uuid();
43+
}
44+
45+
$userSuppliedData = $model->defaultMetadataTemplate["dc"] ?? [];
46+
$model->defaultMetadataTemplate = ["dc" => ["identifier" => $model->uuid ] + $userSuppliedData ] ;
47+
});
48+
}
49+
50+
public function owner()
51+
{
52+
return $this->morphTo();
53+
}
54+
55+
public function archives()
56+
{
57+
return $this->hasMany('App\Archive', 'account_uuid', 'uuid');
58+
}
59+
60+
public function users()
61+
{
62+
return $this->hasMany('App\User', 'account_uuid', 'uuid');
63+
}
64+
65+
public function getDefaultMetadataTemplateAttribute( string $template ) {
66+
$ar = json_decode( $template, true );
67+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["identifier"] ) ) {
68+
$ar["dc"]["identifier"] = $this->attributes["uuid"]; //The default is to use the uuid for the Archive as the identifier (as per spec.)
69+
}
70+
71+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["title"] ) ) {
72+
$ar["dc"]["title"] = $this->attributes["title"] ?? ""; //TODO: accounts.title is nullable, not sure if this is ok?
73+
}
74+
75+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["description"] ) ) {
76+
$ar["dc"]["description"] = $this->attributes["description"] ?? ""; //Grab the description from the model if not present in metadata template
77+
}
78+
return $ar;
79+
}
80+
81+
}

app/AccountMetadata.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use App\Traits\MorphableSelf;
6+
7+
class AccountMetadata extends Metadata
8+
{
9+
use MorphableSelf;
10+
}

app/Archive.php

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,49 @@
22

33
namespace App;
44

5+
use App\Traits\AutoGenerateUuid;
56
use Illuminate\Database\Eloquent\Model;
67
use Illuminate\Database\Eloquent\SoftDeletes;
78
use Webpatser\Uuid\Uuid;
8-
9+
use Illuminate\Support\Str;
10+
use Illuminate\Support\Facades\Validator;
911

1012
class Archive extends Model
1113
{
1214
use SoftDeletes;
15+
use AutoGenerateUuid;
16+
17+
const DEFAULT_TEMPLATE = '{ "title": "", "description": "", "dc": { "identifier": "" } }';
1318

1419
protected $table = 'archives';
1520
protected $fillable = [
16-
'title','description','parent_uuid', 'uuid'
21+
'title','description','parent_uuid', 'uuid', 'account_uuid', 'defaultMetadataTemplate'
22+
];
23+
protected $casts = [
24+
'defaultMetadataTemplate' => 'array'
25+
];
26+
27+
protected $attributes = [
28+
'defaultMetadataTemplate' => self::DEFAULT_TEMPLATE
1729
];
1830

31+
1932
protected static function boot()
2033
{
2134
parent::boot();
22-
static::creating(function ($model) {
23-
if(empty($model->uuid)){
24-
$model->uuid = Uuid::generate()->string;
35+
36+
static::creating( function ( $model ) {
37+
$validateIdentifier = Validator::make( ['uuid' => $model->uuid ], ['uuid' => 'uuid'] );
38+
if( !$validateIdentifier->passes() ){
39+
$model->uuid = Str::uuid();
2540
}
41+
42+
/* No identifier supplied, create one */
43+
$userSuppliedData = $model->defaultMetadataTemplate["dc"];
44+
$model->defaultMetadataTemplate = ["dc" => ["identifier" => $model->uuid ] + $userSuppliedData ] ;
2645
});
2746
}
28-
47+
2948
public static function findByParentUuid($parent_uuid)
3049
{
3150
return Archive::where('parent_uuid', '=', $parent_uuid)->first();
@@ -54,5 +73,30 @@ public function holdings()
5473
return $this->hasMany('App\Holding', 'owner_archive_uuid', 'uuid');
5574
}
5675

76+
public function account() {
77+
return $this->belongsTo(\App\Account::class, 'account_uuid', 'uuid');
78+
}
79+
80+
public function getDefaultMetadataTemplateAttribute( string $template ) {
81+
$ar = json_decode( $template, true );
82+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["identifier"] ) ) {
83+
$ar["dc"]["identifier"] = $this->attributes["uuid"]; //The default is to use the uuid for the Archive as the identifier (as per spec.)
84+
}
85+
86+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["title"] ) ) {
87+
$ar["dc"]["title"] = $this->attributes["title"]; //Grab the title from the model if not present in metadata template
88+
}
89+
90+
if(isset( $ar["dc"] ) && !isset( $ar["dc"]["description"] ) ) {
91+
$ar["dc"]["description"] = $this->attributes["description"] ?? ""; //Grab the description from the model if not present in metadata template
5792

93+
}
94+
return $ar;
95+
}
96+
97+
public function setDefaultMetadataTemplateAttribute( Array $template ) {
98+
if( array_has( $template, 'dc' ) ) { //TODO: Support other schemas than DC, model level validation would be nice
99+
$this->attributes['defaultMetadataTemplate'] = json_encode( $template );
100+
}
101+
}
58102
}

app/ArchiveMetadata.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use App\Traits\AutoGenerateUuid;
6+
use App\Traits\MorphableSelf;
7+
8+
class ArchiveMetadata extends Metadata
9+
{
10+
use MorphableSelf;
11+
}

app/Auth/User.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace App\Auth;
4+
5+
use App\File;
6+
use Exception;
7+
use Illuminate\Foundation\Auth\User as Authenticatable;
8+
9+
class User extends Authenticatable
10+
{
11+
public function getIdAttribute()
12+
{
13+
return isset($this->token) ? $this->token->sub : $this->sub;
14+
}
15+
16+
public function settings()
17+
{
18+
//todo: remove this at the point when we can create keycloak users via this client
19+
if(!\App\UserSetting::where([ 'user_id' => $this->getIdAttribute()])->exists())
20+
\App\UserSetting::create([ 'user_id' => $this->getIdAttribute() ]);
21+
return $this->hasOne('App\UserSetting', 'user_id');
22+
}
23+
24+
public function bags()
25+
{
26+
return $this->hasMany('App\Bag', 'owner');
27+
}
28+
29+
public function jobs()
30+
{
31+
return $this->hasMany('App\Job', 'owner');
32+
}
33+
34+
public function aips()
35+
{
36+
return $this->hasMany('App\Aip', 'owner');
37+
}
38+
39+
public function dips()
40+
{
41+
return $this->hasMany('App\Dip', 'owner');
42+
}
43+
44+
public function storageLocations()
45+
{
46+
return $this->hasMany('App\StorageLocation', 'owner_id');
47+
}
48+
49+
public function save(array $options = [])
50+
{
51+
$id = $this->getIdAttribute();
52+
try {
53+
$dir=storage_path("app/data/keycloak/users/");
54+
if(!File::isDirectory($dir))File::makeDirectory($dir, 0777, true, true);
55+
file_put_contents(storage_path("app/data/keycloak/users/$id.json"), $this->toJson()['token']);
56+
} catch (Exception $e) {
57+
return false;
58+
}
59+
return true;
60+
}
61+
62+
public function withAccessToken($accessToken)
63+
{
64+
$this->accessToken = $accessToken;
65+
return $this;
66+
}
67+
68+
public function getAccountUuidAttribute()
69+
{
70+
/* TODO: Get rid of this hacky workaround -
71+
the auth user model must support everything the eloquent user model does! */
72+
return \App\User::find( auth()->id() )->account->uuid;
73+
}
74+
75+
public function getUsernameAttribute()
76+
{
77+
/* TODO: Get rid of this hacky workaround -
78+
the auth user model must support everything the eloquent user model does! */
79+
return \App\User::find( auth()->id() )->username;
80+
}
81+
82+
83+
public function account()
84+
{
85+
return \App\User::find( auth()->id() )->account();
86+
}
87+
88+
}

0 commit comments

Comments
 (0)