Skip to content

link.tools.install

main(content_source, bip_source=DEFAULT_SOURCE, version=None, python_package_repository=None, username=DEFAULT_USERNAME, password=DEFAULT_PASSWORD, clear_database=False, populate_default=True)

Initializes an empty Neo4j database for Bip.

Creates elementary data in order to make the database compatible with Bip. - Default user privileges: admin, user and guest. - Default user role: internal. - Default user with admin privilege. If not specified, the username will be "admin" and the password will be "bip".

This function must be executed on an empty database.

Parameters:

Name Type Description Default
content_source str

A valid git url to a content repository.

required
bip_source str

A valid git url to a Bip repository. - Use this parameter if you are using your own fork of Bip. - The official repository is use if unspecified.

DEFAULT_SOURCE
version str

Version number. Defaults to None. - It must be an existing model in the bip_source repository. Formatted like so vX.X.X. - If left to None, the most recent model found in the bip_source repository is used.

None
username str

If set, it will override the default username ("admin") Must contain only alphanumerical characters, dashes, dots and underscores.

DEFAULT_USERNAME
password str

If set, it will override the default password ("bip")

DEFAULT_PASSWORD

Returns:

Name Type Description
Config

The server config object that has been created.

Raises:

Type Description
ValueError
  • The database is already populated.
  • The username contains forbidden characters
  • The server config already exists on the server.
  • content_source is not a valid Git repository.
  • bip_source is not a valid Git repository.
  • version is not found in the bip_source repository models.
Source code in client/bip/link/tools/install.py
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
def main(
    content_source,
    bip_source=DEFAULT_SOURCE,
    version=None,
    python_package_repository=None,
    username=DEFAULT_USERNAME,
    password=DEFAULT_PASSWORD,
    clear_database=False,
    populate_default=True,
):
    """Initializes an empty Neo4j database for Bip.

    Creates elementary data in order to make the database
    compatible with Bip.
    - Default user privileges: admin, user and guest.
    - Default user role: internal.
    - Default user with admin privilege. If not specified, the username
    will be "_admin_" and the password will be "_bip_".

    This function must be executed on an **empty database**.

    Args:
        content_source (str): A valid git url to a content repository.
        bip_source (str, optional): A valid git url to a Bip repository.
            - Use this parameter if you are using your own fork of Bip.
            - The official repository is use if unspecified.
        version (str, optional): Version number. Defaults to None.
            - It must be an existing model in the `bip_source` repository. Formatted like so `vX.X.X`.
            - If left to None, the most recent model found in the bip_source repository is used.
        username (str, optional): If set, it will override the default username ("admin")
            Must contain only alphanumerical characters, dashes, dots and underscores.
        password (str, optional): If set, it will override the default password ("bip")

    Returns:
        Config: The server config object that has been created.

    Raises:
        ValueError:
            - The database is already populated.
            - The username contains forbidden characters
            - The server config already exists on the server.
            - `content_source` is not a valid Git repository.
            - `bip_source` is not a valid Git repository.
            - `version` is not found in the `bip_source` repository models.
    """
    if clear_database:
        link.logger.info("Install: clear database.")
        sink.utils.reset_database()

    os.environ["_BIP_IGNORE_PERMISSIONS"] = "1"

    # Check if the database is empty
    if not database.is_empty():
        raise ValueError("Impossible to initialize the database if it not empty.")

    # Check if username is valid (no special characters)
    # Even if this test if made in the user validation,
    # we test this before in order to make sure that the user creation
    # won't fail after the roles and privileges have been created.
    if any(char in username for char in link.user.FORBIDDEN_CHARACTERS):
        raise ValueError(
            "The username cannot contain special characters apart from the dash, the underscore and the period"
        )

    # Create default constraints
    link.logger.info("Install: create default Neo4j constraints.")
    uided_entities = [
        "ProjectModel",
        "Project",
        "ItemModel",
        "Item",
        "GroupModel",
        "Group",
        "DocumentModel",
        "Document",
        "Version",
        "TaskModel",
        "Task",
        "Status",
        "User",
        "Config",
        "PluginSource",
        "PluginSettings",
        "Plugin",
        "MetaModel",
    ]

    for entity in uided_entities:
        sink.internal.make_uid_unique(entity)

    # Check if server setting exists
    try:
        link.config.get()
    except LookupError:
        pass
    else:
        raise ValueError("This Bip server already has a config")

    if not check_git_repo_validity(content_source):
        raise ValueError(f"{content_source} is not a valid Git repository")

    if not check_git_repo_validity(bip_source):
        raise ValueError(f"{bip_source} is not a valid Git repository")

    link.logger.info("Install: get client repository latest version tag.")
    models = get_remote_tags(bip_source)
    versions = sorted(models.keys(), key=lambda v: packaging.version.parse(v))
    latest_tag = versions[-1]

    if not version:
        version = latest_tag

    # Create Config
    link.logger.info("Install: create Bip config.")
    config = link.config.Config()
    config.version = version
    config.content_source = content_source
    config.bip_source = bip_source
    config.permissions = DEFAULT_PERMISSIONS
    config.python_package_repository = python_package_repository
    if python_package_repository:
        config.offline = True

    # Default options
    config.enable_announcement = True
    config.announcement_message = "Welcome to Bip!"
    config.announcement_level = INFO
    config.closable_announcement = True
    config.active_project_timeout = 7  # days

    config.save()

    # Create internal source plugins
    # Register core and circle plugins
    link.logger.info("Install: register core and circle plugins.")
    with open(internal_plugins_path, mode="rb") as file_content:
        internal_plugins = yaml.safe_load(file_content)

    for url in {**internal_plugins["core"], **internal_plugins["circle"]}.values():
        link.plugin.register(url)

    # Enable core plugins
    link.logger.info("Install: enable core plugins.")
    sources = [s for s in link.plugin.get_sources() if s.level == CORE]
    for source in sources:
        source.enable(version=source.get_latest_version())

    # Create privileges
    link.logger.info("Install: create default privileges.")
    for slug in DEFAULT_PRIVILEGES:
        name = slug.capitalize()
        link.user.new_privilege(name, slug)

    # Create roles
    link.logger.info("Install: create default roles.")
    for slug in DEFAULT_ROLES:
        name = slug.capitalize()
        link.user.new_role(name, slug=slug)

    # Create user
    link.logger.info("Install: create default user.")
    link.user.new_user(
        username=username,
        password=password,
        initials=username[:2].upper(),
        first_name=username.capitalize(),
        last_name=username.capitalize(),
        privilege=link.user.get_privilege(slug="administrator"),
        role=link.user.get_role(slug="internal"),
    )

    # Default project
    if populate_default:
        link.logger.info("Install: create basic project.")
        basic_model_descriptor = Path(builtins_directory) / "models" / "basic.yml"
        link.meta.register_from_file(basic_model_descriptor)

        basic_model = link.project.new_model(
            name="Basic project", path_pattern="{self}", slug="basic"
        )

        model = link.meta.get("basic")
        project = link.project.new("Demo project", model, slug="demo", model=basic_model)

        os.environ["_BIP_IGNORE_PERMISSIONS"] = "0"

    return config